OSDN Git Service

* sparc-protos.h (select_cc_mode): Declare.
[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-98, 1999, 2000 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 ;; Uses of UNSPEC and UNSPEC_VOLATILE in this file:
27 ;;
28 ;; UNSPEC:              0       movsi_{lo_sum,high}_pic
29 ;;                              pic_lo_sum_di
30 ;;                              pic_sethi_di
31 ;;                      1       update_return
32 ;;                      2       get_pc
33 ;;                      5       movsi_{,lo_sum_,high_}pic_label_ref
34 ;;                      6       seth44
35 ;;                      7       setm44
36 ;;                      8       setl44
37 ;;                      9       sethh
38 ;;                      10      setlm
39 ;;                      11      embmedany_sethi, embmedany_brsum
40 ;;                      13      embmedany_textuhi
41 ;;                      14      embmedany_texthi
42 ;;                      15      embmedany_textulo
43 ;;                      16      embmedany_textlo
44 ;;                      18      sethm
45 ;;                      19      setlo
46 ;;
47 ;; UNSPEC_VOLATILE:     0       blockage
48 ;;                      1       flush_register_windows
49 ;;                      2       goto_handler_and_restore
50 ;;                      3       goto_handler_and_restore_v9*
51 ;;                      4       flush
52 ;;                      5       nonlocal_goto_receiver
53 ;;
54
55 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
56 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
57 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
58 ;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
59 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
60 ;;
61 ;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to
62 ;; test TARGET_LIVE_G0 if we have TARGET_ARCH64.
63
64 ;; Attribute for cpu type.
65 ;; These must match the values for enum processor_type in sparc.h.
66 (define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,hypersparc,sparclite86x,sparclet,tsc701,v9,ultrasparc"
67   (const (symbol_ref "sparc_cpu_attr")))
68
69 ;; Attribute for the instruction set.
70 ;; At present we only need to distinguish v9/!v9, but for clarity we
71 ;; test TARGET_V8 too.
72 (define_attr "isa" "v6,v8,v9,sparclet"
73  (const
74   (cond [(symbol_ref "TARGET_V9") (const_string "v9")
75          (symbol_ref "TARGET_V8") (const_string "v8")
76          (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
77         (const_string "v6"))))
78
79 ;; Architecture size.
80 (define_attr "arch" "arch32bit,arch64bit"
81  (const
82   (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
83         (const_string "arch32bit"))))
84
85 ;; Whether -mlive-g0 is in effect.
86 (define_attr "live_g0" "no,yes"
87  (const
88   (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
89         (const_string "no"))))
90
91 ;; Insn type.  Used to default other attribute values.
92
93 ;; type "unary" insns have one input operand (1) and one output operand (0)
94 ;; type "binary" insns have two input operands (1,2) and one output (0)
95 ;; type "compare" insns have one or two input operands (0,1) and no output
96 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
97
98 (define_attr "type"
99   "move,unary,binary,compare,load,sload,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,return,address,imul,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
100   (const_string "binary"))
101
102 ;; Set true if insn uses call-clobbered intermediate register.
103 (define_attr "use_clobbered" "false,true"
104   (if_then_else (and (eq_attr "type" "address")
105                      (match_operand 0 "clobbered_register" ""))
106                 (const_string "true")
107                 (const_string "false")))
108
109 ;; Length (in # of insns).
110 (define_attr "length" ""
111   (cond [(eq_attr "type" "load,sload,fpload")
112          (if_then_else (match_operand 1 "symbolic_memory_operand" "")
113                        (const_int 2) (const_int 1))
114
115          (eq_attr "type" "store,fpstore")
116          (if_then_else (match_operand 0 "symbolic_memory_operand" "")
117                        (const_int 2) (const_int 1))
118
119          (eq_attr "type" "address") (const_int 2)
120
121          (eq_attr "type" "binary")
122          (if_then_else (ior (match_operand 2 "arith_operand" "")
123                             (match_operand 2 "arith_double_operand" ""))
124                        (const_int 1) (const_int 3))
125
126          (eq_attr "type" "multi") (const_int 2)
127
128          (eq_attr "type" "move,unary")
129          (if_then_else (ior (match_operand 1 "arith_operand" "")
130                             (match_operand 1 "arith_double_operand" ""))
131                        (const_int 1) (const_int 2))]
132
133         (const_int 1)))
134
135 (define_asm_attributes
136   [(set_attr "length" "1")
137    (set_attr "type" "multi")])
138
139 ;; Attributes for instruction and branch scheduling
140
141 (define_attr "in_call_delay" "false,true"
142   (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,return,multi")
143                 (const_string "false")
144          (eq_attr "type" "load,fpload,store,fpstore")
145                 (if_then_else (eq_attr "length" "1")
146                               (const_string "true")
147                               (const_string "false"))
148          (eq_attr "type" "address")
149                 (if_then_else (eq_attr "use_clobbered" "false")
150                               (const_string "true")
151                               (const_string "false"))]
152         (if_then_else (eq_attr "length" "1")
153                       (const_string "true")
154                       (const_string "false"))))
155
156 (define_delay (eq_attr "type" "call")
157   [(eq_attr "in_call_delay" "true") (nil) (nil)])
158
159 (define_attr "leaf_function" "false,true"
160   (const (symbol_ref "current_function_uses_only_leaf_regs")))
161
162 (define_attr "eligible_for_return_delay" "false,true"
163   (symbol_ref "eligible_for_return_delay(insn)"))
164
165 (define_attr "in_return_delay" "false,true"
166   (if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
167                                (eq_attr "length" "1"))
168                           (eq_attr "leaf_function" "false"))
169                      (eq_attr "eligible_for_return_delay" "false"))
170                 (const_string "true")
171                 (const_string "false")))
172
173 (define_delay (and (eq_attr "type" "return")
174                    (eq_attr "isa" "v9"))
175   [(eq_attr "in_return_delay" "true") (nil) (nil)])
176
177 ;; ??? Should implement the notion of predelay slots for floating point
178 ;; branches.  This would allow us to remove the nop always inserted before
179 ;; a floating point branch.
180
181 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
182 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
183 ;; This is because doing so will add several pipeline stalls to the path
184 ;; that the load/store did not come from.  Unfortunately, there is no way
185 ;; to prevent fill_eager_delay_slots from using load/store without completely
186 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
187 ;; because it prevents us from moving back the final store of inner loops.
188
189 (define_attr "in_branch_delay" "false,true"
190   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
191                      (eq_attr "length" "1"))
192                 (const_string "true")
193                 (const_string "false")))
194
195 (define_attr "in_uncond_branch_delay" "false,true"
196   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
197                      (eq_attr "length" "1"))
198                 (const_string "true")
199                 (const_string "false")))
200
201 (define_attr "in_annul_branch_delay" "false,true"
202   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
203                      (eq_attr "length" "1"))
204                 (const_string "true")
205                 (const_string "false")))
206
207 (define_delay (eq_attr "type" "branch")
208   [(eq_attr "in_branch_delay" "true")
209    (nil) (eq_attr "in_annul_branch_delay" "true")])
210
211 (define_delay (eq_attr "type" "uncond_branch")
212   [(eq_attr "in_uncond_branch_delay" "true")
213    (nil) (nil)])
214    
215 ;; Function units of the SPARC
216
217 ;; (define_function_unit {name} {num-units} {n-users} {test}
218 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
219
220 ;; The integer ALU.
221 ;; (Noted only for documentation; units that take one cycle do not need to
222 ;; be specified.)
223
224 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
225 ;; the inputs.
226
227 ;; (define_function_unit "alu" 1 0
228 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
229
230 ;; ---- cypress CY7C602 scheduling:
231 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
232
233 (define_function_unit "memory" 1 0 
234   (and (eq_attr "cpu" "cypress")
235     (eq_attr "type" "load,sload,fpload"))
236   2 2)
237
238 ;; SPARC has two floating-point units: the FP ALU,
239 ;; and the FP MUL/DIV/SQRT unit.
240 ;; Instruction timings on the CY7C602 are as follows
241 ;; FABSs        4
242 ;; FADDs/d      5/5
243 ;; FCMPs/d      4/4
244 ;; FDIVs/d      23/37
245 ;; FMOVs        4
246 ;; FMULs/d      5/7
247 ;; FNEGs        4
248 ;; FSQRTs/d     34/63
249 ;; FSUBs/d      5/5
250 ;; FdTOi/s      5/5
251 ;; FsTOi/d      5/5
252 ;; FiTOs/d      9/5
253
254 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
255 ;; More insns cause the chip to stall.
256
257 (define_function_unit "fp_alu" 1 0
258   (and (eq_attr "cpu" "cypress")
259     (eq_attr "type" "fp,fpmove"))
260   5 5)
261
262 (define_function_unit "fp_mds" 1 0
263   (and (eq_attr "cpu" "cypress")
264     (eq_attr "type" "fpmul"))
265   7 7)
266
267 (define_function_unit "fp_mds" 1 0
268   (and (eq_attr "cpu" "cypress")
269     (eq_attr "type" "fpdivs,fpdivd"))
270   37 37)
271
272 (define_function_unit "fp_mds" 1 0
273   (and (eq_attr "cpu" "cypress")
274     (eq_attr "type" "fpsqrts,fpsqrtd"))
275   63 63)
276
277 ;; ----- The TMS390Z55 scheduling
278 ;; The Supersparc can issue 1 - 3 insns per cycle: up to two integer,
279 ;; one ld/st, one fp.
280 ;; Memory delivers its result in one cycle to IU, zero cycles to FP
281
282 (define_function_unit "memory" 1 0
283   (and (eq_attr "cpu" "supersparc")
284     (eq_attr "type" "load,sload"))
285   1 1)
286
287 (define_function_unit "memory" 1 0
288   (and (eq_attr "cpu" "supersparc")
289     (eq_attr "type" "fpload"))
290   0 1)
291
292 (define_function_unit "memory" 1 0
293   (and (eq_attr "cpu" "supersparc")
294     (eq_attr "type" "store,fpstore"))
295   1 1)
296
297 (define_function_unit "shift" 1 0
298   (and (eq_attr "cpu" "supersparc")
299     (eq_attr "type" "shift"))
300   1 1)
301
302 ;; There are only two write ports to the integer register file
303 ;; A store also uses a write port
304
305 (define_function_unit "iwport" 2 0
306   (and (eq_attr "cpu" "supersparc")
307     (eq_attr "type" "load,sload,store,shift,ialu"))
308   1 1)
309
310 ;; Timings; throughput/latency
311 ;; FADD     1/3    add/sub, format conv, compar, abs, neg
312 ;; FMUL     1/3
313 ;; FDIVs    4/6
314 ;; FDIVd    7/9
315 ;; FSQRTs   6/8
316 ;; FSQRTd  10/12
317 ;; IMUL     4/4
318
319 (define_function_unit "fp_alu" 1 0
320   (and (eq_attr "cpu" "supersparc")
321     (eq_attr "type" "fp,fpmove,fpcmp"))
322   3 1)
323
324 (define_function_unit "fp_mds" 1 0
325   (and (eq_attr "cpu" "supersparc")
326     (eq_attr "type" "fpmul"))
327   3 1)
328
329 (define_function_unit "fp_mds" 1 0
330   (and (eq_attr "cpu" "supersparc")
331     (eq_attr "type" "fpdivs"))
332   6 4)
333
334 (define_function_unit "fp_mds" 1 0
335   (and (eq_attr "cpu" "supersparc")
336     (eq_attr "type" "fpdivd"))
337   9 7)
338
339 (define_function_unit "fp_mds" 1 0
340   (and (eq_attr "cpu" "supersparc")
341     (eq_attr "type" "fpsqrts,fpsqrtd"))
342   12 10)
343
344 (define_function_unit "fp_mds" 1 0
345   (and (eq_attr "cpu" "supersparc")
346     (eq_attr "type" "imul"))
347   4 4)
348
349 ;; ----- hypersparc/sparclite86x scheduling
350 ;; The Hypersparc can issue 1 - 2 insns per cycle.  The dual issue cases are:
351 ;; L-Ld/St I-Int F-Float B-Branch LI/LF/LB/II/IF/IB/FF/FB
352 ;; II/FF case is only when loading a 32 bit hi/lo constant
353 ;; Single issue insns include call, jmpl, u/smul, u/sdiv, lda, sta, fcmp
354 ;; Memory delivers its result in one cycle to IU
355
356 (define_function_unit "memory" 1 0
357   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
358     (eq_attr "type" "load,sload,fpload"))
359   1 1)
360
361 (define_function_unit "memory" 1 0
362   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
363     (eq_attr "type" "store,fpstore"))
364   2 1)
365
366 (define_function_unit "sparclite86x_branch" 1 0
367   (and (eq_attr "cpu" "sparclite86x")
368     (eq_attr "type" "branch"))
369   1 1)
370
371 ;; integer multiply insns 
372 (define_function_unit "sparclite86x_shift" 1 0
373   (and (eq_attr "cpu" "sparclite86x")
374     (eq_attr "type" "shift"))
375   1 1)
376
377 (define_function_unit "fp_alu" 1 0
378   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
379     (eq_attr "type" "fp,fpmove,fpcmp"))
380   1 1)
381
382 (define_function_unit "fp_mds" 1 0
383   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
384     (eq_attr "type" "fpmul"))
385   1 1)
386
387 (define_function_unit "fp_mds" 1 0
388   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
389     (eq_attr "type" "fpdivs"))
390   8 6)
391
392 (define_function_unit "fp_mds" 1 0
393   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
394     (eq_attr "type" "fpdivd"))
395   12 10)
396
397 (define_function_unit "fp_mds" 1 0
398   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
399     (eq_attr "type" "fpsqrts,fpsqrtd"))
400   17 15)
401
402 (define_function_unit "fp_mds" 1 0
403   (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
404     (eq_attr "type" "imul"))
405   17 15)
406
407 ;; ----- sparclet tsc701 scheduling
408 ;; The tsc701 issues 1 insn per cycle.
409 ;; Results may be written back out of order.
410
411 ;; Loads take 2 extra cycles to complete and 4 can be buffered at a time.
412
413 (define_function_unit "tsc701_load" 4 1
414   (and (eq_attr "cpu" "tsc701")
415     (eq_attr "type" "load,sload"))
416   3 1)
417
418 ;; Stores take 2(?) extra cycles to complete.
419 ;; It is desirable to not have any memory operation in the following 2 cycles.
420 ;; (??? or 2 memory ops in the case of std).
421
422 (define_function_unit "tsc701_store" 1 0
423   (and (eq_attr "cpu" "tsc701")
424     (eq_attr "type" "store"))
425   3 3
426   [(eq_attr "type" "load,sload,store")])
427
428 ;; The multiply unit has a latency of 5.
429 (define_function_unit "tsc701_mul" 1 0
430   (and (eq_attr "cpu" "tsc701")
431     (eq_attr "type" "imul"))
432   5 5)
433
434 ;; ----- The UltraSPARC-1 scheduling
435 ;; UltraSPARC has two integer units.  Shift instructions can only execute
436 ;; on IE0.  Condition code setting instructions, call, and jmpl (including
437 ;; the ret and retl pseudo-instructions) can only execute on IE1.
438 ;; Branch on register uses IE1, but branch on condition code does not.
439 ;; Conditional moves take 2 cycles.  No other instruction can issue in the
440 ;; same cycle as a conditional move.
441 ;; Multiply and divide take many cycles during which no other instructions
442 ;; can issue.
443 ;; Memory delivers its result in two cycles (except for signed loads,
444 ;; which take one cycle more).  One memory instruction can be issued per
445 ;; cycle.
446
447 (define_function_unit "memory" 1 0
448   (and (eq_attr "cpu" "ultrasparc")
449     (eq_attr "type" "load,fpload"))
450   2 1)
451
452 (define_function_unit "memory" 1 0
453   (and (eq_attr "cpu" "ultrasparc")
454     (eq_attr "type" "sload"))
455   3 1)
456
457 (define_function_unit "memory" 1 0
458   (and (eq_attr "cpu" "ultrasparc")
459     (eq_attr "type" "store,fpstore"))
460   1 1)
461
462 (define_function_unit "ieuN" 2 0
463   (and (eq_attr "cpu" "ultrasparc")
464     (eq_attr "type" "ialu,binary,move,unary,shift,compare,call,call_no_delay_slot,uncond_branch"))
465   1 1)
466
467 (define_function_unit "ieu0" 1 0
468   (and (eq_attr "cpu" "ultrasparc")
469     (eq_attr "type" "shift"))
470   1 1)
471
472 (define_function_unit "ieu0" 1 0
473   (and (eq_attr "cpu" "ultrasparc")
474     (eq_attr "type" "cmove"))
475   2 1)
476
477 (define_function_unit "ieu1" 1 0
478   (and (eq_attr "cpu" "ultrasparc")
479     (eq_attr "type" "compare,call,call_no_delay_slot,uncond_branch"))
480   1 1)
481
482 (define_function_unit "cti" 1 0
483   (and (eq_attr "cpu" "ultrasparc")
484     (eq_attr "type" "branch"))
485   1 1)
486
487 ;; Timings; throughput/latency
488 ;; FMOV     1/1    fmov, fabs, fneg
489 ;; FMOVcc   1/2
490 ;; FADD     1/3    add/sub, format conv, compar
491 ;; FMUL     1/3
492 ;; FDIVs    12/12
493 ;; FDIVd    22/22
494 ;; FSQRTs   12/12
495 ;; FSQRTd   22/22
496 ;; FCMP takes 1 cycle to branch, 2 cycles to conditional move.
497 ;;
498 ;; FDIV{s,d}/FSQRT{s,d} are given their own unit since they only
499 ;; use the FPM multiplier for final rounding 3 cycles before the
500 ;; end of their latency and we have no real way to model that.
501 ;;
502 ;; ??? This is really bogus because the timings really depend upon
503 ;; who uses the result.  We should record who the user is with
504 ;; more descriptive 'type' attribute names and account for these
505 ;; issues in ultrasparc_adjust_cost. 
506
507 (define_function_unit "fadd" 1 0
508   (and (eq_attr "cpu" "ultrasparc")
509     (eq_attr "type" "fpmove"))
510   1 1)
511
512 (define_function_unit "fadd" 1 0
513   (and (eq_attr "cpu" "ultrasparc")
514     (eq_attr "type" "fpcmove"))
515   2 1)
516
517 (define_function_unit "fadd" 1 0
518   (and (eq_attr "cpu" "ultrasparc")
519     (eq_attr "type" "fp"))
520   3 1)
521
522 (define_function_unit "fadd" 1 0
523   (and (eq_attr "cpu" "ultrasparc")
524     (eq_attr "type" "fpcmp"))
525   2 1)
526
527 (define_function_unit "fmul" 1 0
528   (and (eq_attr "cpu" "ultrasparc")
529     (eq_attr "type" "fpmul"))
530   3 1)
531
532 (define_function_unit "fadd" 1 0
533   (and (eq_attr "cpu" "ultrasparc")
534     (eq_attr "type" "fpcmove"))
535   2 1)
536
537 (define_function_unit "fdiv" 1 0
538   (and (eq_attr "cpu" "ultrasparc")
539     (eq_attr "type" "fpdivs"))
540   12 12)
541
542 (define_function_unit "fdiv" 1 0
543   (and (eq_attr "cpu" "ultrasparc")
544     (eq_attr "type" "fpdivd"))
545   22 22)
546
547 (define_function_unit "fdiv" 1 0
548   (and (eq_attr "cpu" "ultrasparc")
549     (eq_attr "type" "fpsqrts"))
550   12 12)
551
552 (define_function_unit "fdiv" 1 0
553   (and (eq_attr "cpu" "ultrasparc")
554     (eq_attr "type" "fpsqrtd"))
555   22 22)
556 \f
557 ;; Compare instructions.
558 ;; This controls RTL generation and register allocation.
559
560 ;; We generate RTL for comparisons and branches by having the cmpxx 
561 ;; patterns store away the operands.  Then, the scc and bcc patterns
562 ;; emit RTL for both the compare and the branch.
563 ;;
564 ;; We do this because we want to generate different code for an sne and
565 ;; seq insn.  In those cases, if the second operand of the compare is not
566 ;; const0_rtx, we want to compute the xor of the two operands and test
567 ;; it against zero.
568 ;;
569 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
570 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
571 ;; insns that actually require more than one machine instruction.
572
573 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
574
575 (define_expand "cmpsi"
576   [(set (reg:CC 100)
577         (compare:CC (match_operand:SI 0 "register_operand" "")
578                     (match_operand:SI 1 "arith_operand" "")))]
579   ""
580   "
581 {
582   sparc_compare_op0 = operands[0];
583   sparc_compare_op1 = operands[1];
584   DONE;
585 }")
586
587 (define_expand "cmpdi"
588   [(set (reg:CCX 100)
589         (compare:CCX (match_operand:DI 0 "register_operand" "")
590                      (match_operand:DI 1 "arith_double_operand" "")))]
591   "TARGET_ARCH64"
592   "
593 {
594   sparc_compare_op0 = operands[0];
595   sparc_compare_op1 = operands[1];
596   DONE;
597 }")
598
599 (define_expand "cmpsf"
600   ;; The 96 here isn't ever used by anyone.
601   [(set (reg:CCFP 96)
602         (compare:CCFP (match_operand:SF 0 "register_operand" "")
603                       (match_operand:SF 1 "register_operand" "")))]
604   "TARGET_FPU"
605   "
606 {
607   sparc_compare_op0 = operands[0];
608   sparc_compare_op1 = operands[1];
609   DONE;
610 }")
611
612 (define_expand "cmpdf"
613   ;; The 96 here isn't ever used by anyone.
614   [(set (reg:CCFP 96)
615         (compare:CCFP (match_operand:DF 0 "register_operand" "")
616                       (match_operand:DF 1 "register_operand" "")))]
617   "TARGET_FPU"
618   "
619 {
620   sparc_compare_op0 = operands[0];
621   sparc_compare_op1 = operands[1];
622   DONE;
623 }")
624
625 (define_expand "cmptf"
626   ;; The 96 here isn't ever used by anyone.
627   [(set (reg:CCFP 96)
628         (compare:CCFP (match_operand:TF 0 "register_operand" "")
629                       (match_operand:TF 1 "register_operand" "")))]
630   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
631   "
632 {
633   sparc_compare_op0 = operands[0];
634   sparc_compare_op1 = operands[1];
635   DONE;
636 }")
637
638 ;; Now the compare DEFINE_INSNs.
639
640 (define_insn "*cmpsi_insn"
641   [(set (reg:CC 100)
642         (compare:CC (match_operand:SI 0 "register_operand" "r")
643                     (match_operand:SI 1 "arith_operand" "rI")))]
644   ""
645   "cmp\\t%0, %1"
646   [(set_attr "type" "compare")])
647
648 (define_insn "*cmpdi_sp64"
649   [(set (reg:CCX 100)
650         (compare:CCX (match_operand:DI 0 "register_operand" "r")
651                      (match_operand:DI 1 "arith_double_operand" "rHI")))]
652   "TARGET_ARCH64"
653   "cmp\\t%0, %1"
654   [(set_attr "type" "compare")])
655
656 (define_insn "*cmpsf_fpe"
657   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
658         (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
659                        (match_operand:SF 2 "register_operand" "f")))]
660   "TARGET_FPU"
661   "*
662 {
663   if (TARGET_V9)
664     return \"fcmpes\\t%0, %1, %2\";
665   return \"fcmpes\\t%1, %2\";
666 }"
667   [(set_attr "type" "fpcmp")])
668
669 (define_insn "*cmpdf_fpe"
670   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
671         (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
672                        (match_operand:DF 2 "register_operand" "e")))]
673   "TARGET_FPU"
674   "*
675 {
676   if (TARGET_V9)
677     return \"fcmped\\t%0, %1, %2\";
678   return \"fcmped\\t%1, %2\";
679 }"
680   [(set_attr "type" "fpcmp")])
681
682 (define_insn "*cmptf_fpe"
683   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
684         (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
685                        (match_operand:TF 2 "register_operand" "e")))]
686   "TARGET_FPU && TARGET_HARD_QUAD"
687   "*
688 {
689   if (TARGET_V9)
690     return \"fcmpeq\\t%0, %1, %2\";
691   return \"fcmpeq\\t%1, %2\";
692 }"
693   [(set_attr "type" "fpcmp")])
694
695 (define_insn "*cmpsf_fp"
696   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
697         (compare:CCFP (match_operand:SF 1 "register_operand" "f")
698                       (match_operand:SF 2 "register_operand" "f")))]
699   "TARGET_FPU"
700   "*
701 {
702   if (TARGET_V9)
703     return \"fcmps\\t%0, %1, %2\";
704   return \"fcmps\\t%1, %2\";
705 }"
706   [(set_attr "type" "fpcmp")])
707
708 (define_insn "*cmpdf_fp"
709   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
710         (compare:CCFP (match_operand:DF 1 "register_operand" "e")
711                       (match_operand:DF 2 "register_operand" "e")))]
712   "TARGET_FPU"
713   "*
714 {
715   if (TARGET_V9)
716     return \"fcmpd\\t%0, %1, %2\";
717   return \"fcmpd\\t%1, %2\";
718 }"
719   [(set_attr "type" "fpcmp")])
720
721 (define_insn "*cmptf_fp"
722   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
723         (compare:CCFP (match_operand:TF 1 "register_operand" "e")
724                       (match_operand:TF 2 "register_operand" "e")))]
725   "TARGET_FPU && TARGET_HARD_QUAD"
726   "*
727 {
728   if (TARGET_V9)
729     return \"fcmpq\\t%0, %1, %2\";
730   return \"fcmpq\\t%1, %2\";
731 }"
732   [(set_attr "type" "fpcmp")])
733 \f
734 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
735 ;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
736 ;; the same code as v8 (the addx/subx method has more applications).  The
737 ;; exception to this is "reg != 0" which can be done in one instruction on v9
738 ;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
739 ;; branches.
740
741 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
742 ;; generate addcc/subcc instructions.
743
744 (define_expand "seqsi_special"
745   [(set (match_dup 3)
746         (xor:SI (match_operand:SI 1 "register_operand" "")
747                 (match_operand:SI 2 "register_operand" "")))
748    (parallel [(set (match_operand:SI 0 "register_operand" "")
749                    (eq:SI (match_dup 3) (const_int 0)))
750               (clobber (reg:CC 100))])]
751   "! TARGET_LIVE_G0"
752   "{ operands[3] = gen_reg_rtx (SImode); }")
753
754 (define_expand "seqdi_special"
755   [(set (match_dup 3)
756         (xor:DI (match_operand:DI 1 "register_operand" "")
757                 (match_operand:DI 2 "register_operand" "")))
758    (set (match_operand:DI 0 "register_operand" "")
759         (eq:DI (match_dup 3) (const_int 0)))]
760   "TARGET_ARCH64"
761   "{ operands[3] = gen_reg_rtx (DImode); }")
762
763 (define_expand "snesi_special"
764   [(set (match_dup 3)
765         (xor:SI (match_operand:SI 1 "register_operand" "")
766                 (match_operand:SI 2 "register_operand" "")))
767    (parallel [(set (match_operand:SI 0 "register_operand" "")
768                    (ne:SI (match_dup 3) (const_int 0)))
769               (clobber (reg:CC 100))])]
770   "! TARGET_LIVE_G0"
771   "{ operands[3] = gen_reg_rtx (SImode); }")
772
773 (define_expand "snedi_special"
774   [(set (match_dup 3)
775         (xor:DI (match_operand:DI 1 "register_operand" "")
776                 (match_operand:DI 2 "register_operand" "")))
777    (set (match_operand:DI 0 "register_operand" "")
778         (ne:DI (match_dup 3) (const_int 0)))]
779   "TARGET_ARCH64"
780   "{ operands[3] = gen_reg_rtx (DImode); }")
781
782 (define_expand "seqdi_special_trunc"
783   [(set (match_dup 3)
784         (xor:DI (match_operand:DI 1 "register_operand" "")
785                 (match_operand:DI 2 "register_operand" "")))
786    (set (match_operand:SI 0 "register_operand" "")
787         (eq:SI (match_dup 3) (const_int 0)))]
788   "TARGET_ARCH64"
789   "{ operands[3] = gen_reg_rtx (DImode); }")
790
791 (define_expand "snedi_special_trunc"
792   [(set (match_dup 3)
793         (xor:DI (match_operand:DI 1 "register_operand" "")
794                 (match_operand:DI 2 "register_operand" "")))
795    (set (match_operand:SI 0 "register_operand" "")
796         (ne:SI (match_dup 3) (const_int 0)))]
797   "TARGET_ARCH64"
798   "{ operands[3] = gen_reg_rtx (DImode); }")
799
800 (define_expand "seqsi_special_extend"
801   [(set (match_dup 3)
802         (xor:SI (match_operand:SI 1 "register_operand" "")
803                 (match_operand:SI 2 "register_operand" "")))
804    (parallel [(set (match_operand:DI 0 "register_operand" "")
805                    (eq:DI (match_dup 3) (const_int 0)))
806               (clobber (reg:CC 100))])]
807   "TARGET_ARCH64"
808   "{ operands[3] = gen_reg_rtx (SImode); }")
809
810 (define_expand "snesi_special_extend"
811   [(set (match_dup 3)
812         (xor:SI (match_operand:SI 1 "register_operand" "")
813                 (match_operand:SI 2 "register_operand" "")))
814    (parallel [(set (match_operand:DI 0 "register_operand" "")
815                    (ne:DI (match_dup 3) (const_int 0)))
816               (clobber (reg:CC 100))])]
817   "TARGET_ARCH64"
818   "{ operands[3] = gen_reg_rtx (SImode); }")
819
820 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
821 ;; However, the code handles both SImode and DImode.
822 (define_expand "seq"
823   [(set (match_operand:SI 0 "intreg_operand" "")
824         (eq:SI (match_dup 1) (const_int 0)))]
825   "! TARGET_LIVE_G0"
826   "
827 {
828   if (GET_MODE (sparc_compare_op0) == SImode)
829     {
830       rtx pat;
831
832       if (GET_MODE (operands[0]) == SImode)
833         pat = gen_seqsi_special (operands[0], sparc_compare_op0,
834                                  sparc_compare_op1);
835       else if (! TARGET_ARCH64)
836         FAIL;
837       else
838         pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
839                                         sparc_compare_op1);
840       emit_insn (pat);
841       DONE;
842     }
843   else if (GET_MODE (sparc_compare_op0) == DImode)
844     {
845       rtx pat;
846
847       if (! TARGET_ARCH64)
848         FAIL;
849       else if (GET_MODE (operands[0]) == SImode)
850         pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
851                                        sparc_compare_op1);
852       else
853         pat = gen_seqdi_special (operands[0], sparc_compare_op0,
854                                  sparc_compare_op1);
855       emit_insn (pat);
856       DONE;
857     }
858   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
859     {
860       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
861       emit_jump_insn (gen_sne (operands[0]));
862       DONE;
863     }
864   else if (TARGET_V9)
865     {
866       if (gen_v9_scc (EQ, operands))
867         DONE;
868       /* fall through */
869     }
870   FAIL;
871 }")
872
873 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
874 ;; However, the code handles both SImode and DImode.
875 (define_expand "sne"
876   [(set (match_operand:SI 0 "intreg_operand" "")
877         (ne:SI (match_dup 1) (const_int 0)))]
878   "! TARGET_LIVE_G0"
879   "
880 {
881   if (GET_MODE (sparc_compare_op0) == SImode)
882     {
883       rtx pat;
884
885       if (GET_MODE (operands[0]) == SImode)
886         pat = gen_snesi_special (operands[0], sparc_compare_op0,
887                                  sparc_compare_op1);
888       else if (! TARGET_ARCH64)
889         FAIL;
890       else
891         pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
892                                         sparc_compare_op1);
893       emit_insn (pat);
894       DONE;
895     }
896   else if (GET_MODE (sparc_compare_op0) == DImode)
897     {
898       rtx pat;
899
900       if (! TARGET_ARCH64)
901         FAIL;
902       else if (GET_MODE (operands[0]) == SImode)
903         pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
904                                        sparc_compare_op1);
905       else
906         pat = gen_snedi_special (operands[0], sparc_compare_op0,
907                                  sparc_compare_op1);
908       emit_insn (pat);
909       DONE;
910     }
911   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
912     {
913       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
914       emit_jump_insn (gen_sne (operands[0]));
915       DONE;
916     }
917   else if (TARGET_V9)
918     {
919       if (gen_v9_scc (NE, operands))
920         DONE;
921       /* fall through */
922     }
923   FAIL;
924 }")
925
926 (define_expand "sgt"
927   [(set (match_operand:SI 0 "intreg_operand" "")
928         (gt:SI (match_dup 1) (const_int 0)))]
929   "! TARGET_LIVE_G0"
930   "
931 {
932   if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
933     {
934       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
935       emit_jump_insn (gen_sne (operands[0]));
936       DONE;
937     }
938   else if (TARGET_V9)
939     {
940       if (gen_v9_scc (GT, operands))
941         DONE;
942       /* fall through */
943     }
944   FAIL;
945 }")
946
947 (define_expand "slt"
948   [(set (match_operand:SI 0 "intreg_operand" "")
949         (lt:SI (match_dup 1) (const_int 0)))]
950   "! TARGET_LIVE_G0"
951   "
952 {
953   if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
954     {
955       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
956       emit_jump_insn (gen_sne (operands[0]));
957       DONE;
958     }
959   else if (TARGET_V9)
960     {
961       if (gen_v9_scc (LT, operands))
962         DONE;
963       /* fall through */
964     }
965   FAIL;
966 }")
967
968 (define_expand "sge"
969   [(set (match_operand:SI 0 "intreg_operand" "")
970         (ge:SI (match_dup 1) (const_int 0)))]
971   "! TARGET_LIVE_G0"
972   "
973 {
974   if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
975     {
976       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
977       emit_jump_insn (gen_sne (operands[0]));
978       DONE;
979     }
980   else if (TARGET_V9)
981     {
982       if (gen_v9_scc (GE, operands))
983         DONE;
984       /* fall through */
985     }
986   FAIL;
987 }")
988
989 (define_expand "sle"
990   [(set (match_operand:SI 0 "intreg_operand" "")
991         (le:SI (match_dup 1) (const_int 0)))]
992   "! TARGET_LIVE_G0"
993   "
994 {
995   if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
996     {
997       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
998       emit_jump_insn (gen_sne (operands[0]));
999       DONE;
1000     }
1001   else if (TARGET_V9)
1002     {
1003       if (gen_v9_scc (LE, operands))
1004         DONE;
1005       /* fall through */
1006     }
1007   FAIL;
1008 }")
1009
1010 (define_expand "sgtu"
1011   [(set (match_operand:SI 0 "intreg_operand" "")
1012         (gtu:SI (match_dup 1) (const_int 0)))]
1013   "! TARGET_LIVE_G0"
1014   "
1015 {
1016   if (! TARGET_V9)
1017     {
1018       rtx tem, pat;
1019
1020       /* We can do ltu easily, so if both operands are registers, swap them and
1021          do a LTU.  */
1022       if ((GET_CODE (sparc_compare_op0) == REG
1023            || GET_CODE (sparc_compare_op0) == SUBREG)
1024           && (GET_CODE (sparc_compare_op1) == REG
1025               || GET_CODE (sparc_compare_op1) == SUBREG))
1026         {
1027           tem = sparc_compare_op0;
1028           sparc_compare_op0 = sparc_compare_op1;
1029           sparc_compare_op1 = tem;
1030           pat = gen_sltu (operands[0]);
1031           if (pat == NULL_RTX)
1032             FAIL;
1033           emit_insn (pat);
1034           DONE;
1035         }
1036     }
1037   else
1038     {
1039       if (gen_v9_scc (GTU, operands))
1040         DONE;
1041     }
1042   FAIL;
1043 }")
1044
1045 (define_expand "sltu"
1046   [(set (match_operand:SI 0 "intreg_operand" "")
1047         (ltu:SI (match_dup 1) (const_int 0)))]
1048   "! TARGET_LIVE_G0"
1049   "
1050 {
1051   if (TARGET_V9)
1052     {
1053       if (gen_v9_scc (LTU, operands))
1054         DONE;
1055     }
1056   operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1057 }")
1058
1059 (define_expand "sgeu"
1060   [(set (match_operand:SI 0 "intreg_operand" "")
1061         (geu:SI (match_dup 1) (const_int 0)))]
1062   "! TARGET_LIVE_G0"
1063   "
1064 {
1065   if (TARGET_V9)
1066     {
1067       if (gen_v9_scc (GEU, operands))
1068         DONE;
1069     }
1070   operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1071 }")
1072
1073 (define_expand "sleu"
1074   [(set (match_operand:SI 0 "intreg_operand" "")
1075         (leu:SI (match_dup 1) (const_int 0)))]
1076   "! TARGET_LIVE_G0"
1077   "
1078 {
1079   if (! TARGET_V9)
1080     {
1081       rtx tem, pat;
1082
1083       /* We can do geu easily, so if both operands are registers, swap them and
1084          do a GEU.  */
1085       if ((GET_CODE (sparc_compare_op0) == REG
1086            || GET_CODE (sparc_compare_op0) == SUBREG)
1087           && (GET_CODE (sparc_compare_op1) == REG
1088               || GET_CODE (sparc_compare_op1) == SUBREG))
1089         {
1090           tem = sparc_compare_op0;
1091           sparc_compare_op0 = sparc_compare_op1;
1092           sparc_compare_op1 = tem;
1093           pat = gen_sgeu (operands[0]);
1094           if (pat == NULL_RTX)
1095             FAIL;
1096           emit_insn (pat);
1097           DONE;
1098         }
1099     }
1100   else
1101     {
1102       if (gen_v9_scc (LEU, operands))
1103         DONE;
1104     }
1105   FAIL;
1106 }")
1107
1108 ;; Now the DEFINE_INSNs for the scc cases.
1109
1110 ;; The SEQ and SNE patterns are special because they can be done
1111 ;; without any branching and do not involve a COMPARE.  We want
1112 ;; them to always use the splitz below so the results can be
1113 ;; scheduled.
1114
1115 (define_insn "*snesi_zero"
1116   [(set (match_operand:SI 0 "register_operand" "=r")
1117         (ne:SI (match_operand:SI 1 "register_operand" "r")
1118                (const_int 0)))
1119    (clobber (reg:CC 100))]
1120   "! TARGET_LIVE_G0"
1121   "#"
1122   [(set_attr "length" "2")])
1123
1124 (define_split
1125   [(set (match_operand:SI 0 "register_operand" "")
1126         (ne:SI (match_operand:SI 1 "register_operand" "")
1127                (const_int 0)))
1128    (clobber (reg:CC 100))]
1129   ""
1130   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1131                                            (const_int 0)))
1132    (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
1133   "")
1134
1135 (define_insn "*neg_snesi_zero"
1136   [(set (match_operand:SI 0 "register_operand" "=r")
1137         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
1138                        (const_int 0))))
1139    (clobber (reg:CC 100))]
1140   "! TARGET_LIVE_G0"
1141   "#"
1142   [(set_attr "length" "2")])
1143
1144 (define_split
1145   [(set (match_operand:SI 0 "register_operand" "")
1146         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
1147                        (const_int 0))))
1148    (clobber (reg:CC 100))]
1149   ""
1150   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1151                                            (const_int 0)))
1152    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1153   "")
1154
1155 (define_insn "*snesi_zero_extend"
1156   [(set (match_operand:DI 0 "register_operand" "=r")
1157         (ne:DI (match_operand:SI 1 "register_operand" "r")
1158                (const_int 0)))
1159    (clobber (reg:CC 100))]
1160   "TARGET_ARCH64"
1161   "#"
1162   [(set_attr "type" "unary")
1163    (set_attr "length" "2")])
1164
1165 (define_split
1166   [(set (match_operand:DI 0 "register_operand" "")
1167         (ne:DI (match_operand:SI 1 "register_operand" "")
1168                (const_int 0)))
1169    (clobber (reg:CC 100))]
1170   "TARGET_ARCH64"
1171   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
1172                                            (const_int 0)))
1173    (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
1174                                                         (const_int 0))
1175                                                (ltu:SI (reg:CC_NOOV 100)
1176                                                        (const_int 0)))))]
1177   "")
1178
1179 (define_insn "*snedi_zero"
1180   [(set (match_operand:DI 0 "register_operand" "=&r")
1181         (ne:DI (match_operand:DI 1 "register_operand" "r")
1182                (const_int 0)))]
1183   "TARGET_ARCH64"
1184   "#"
1185   [(set_attr "type" "cmove")
1186    (set_attr "length" "2")])
1187
1188 (define_split
1189   [(set (match_operand:DI 0 "register_operand" "")
1190         (ne:DI (match_operand:DI 1 "register_operand" "")
1191                (const_int 0)))]
1192   "TARGET_ARCH64"
1193   [(set (match_dup 0) (const_int 0))
1194    (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
1195                                               (const_int 0))
1196                                        (const_int 1)
1197                                        (match_dup 0)))]
1198   "")
1199
1200 (define_insn "*neg_snedi_zero"
1201   [(set (match_operand:DI 0 "register_operand" "=&r")
1202         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
1203                        (const_int 0))))]
1204   "TARGET_ARCH64"
1205   "#"
1206   [(set_attr "type" "cmove")
1207    (set_attr "length" "2")])
1208
1209 (define_split
1210   [(set (match_operand:DI 0 "register_operand" "")
1211         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "")
1212                        (const_int 0))))]
1213   "TARGET_ARCH64"
1214   [(set (match_dup 0) (const_int 0))
1215    (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
1216                                               (const_int 0))
1217                                        (const_int -1)
1218                                        (match_dup 0)))]
1219   "")
1220
1221 (define_insn "*snedi_zero_trunc"
1222   [(set (match_operand:SI 0 "register_operand" "=&r")
1223         (ne:SI (match_operand:DI 1 "register_operand" "r")
1224                (const_int 0)))]
1225   "TARGET_ARCH64"
1226   "#"
1227   [(set_attr "type" "cmove")
1228    (set_attr "length" "2")])
1229
1230 (define_split
1231   [(set (match_operand:SI 0 "register_operand" "")
1232         (ne:SI (match_operand:DI 1 "register_operand" "")
1233                (const_int 0)))]
1234   "TARGET_ARCH64"
1235   [(set (match_dup 0) (const_int 0))
1236    (set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
1237                                               (const_int 0))
1238                                        (const_int 1)
1239                                        (match_dup 0)))]
1240   "")
1241
1242 (define_insn "*seqsi_zero"
1243   [(set (match_operand:SI 0 "register_operand" "=r")
1244         (eq:SI (match_operand:SI 1 "register_operand" "r")
1245                (const_int 0)))
1246    (clobber (reg:CC 100))]
1247   "! TARGET_LIVE_G0"
1248   "#"
1249   [(set_attr "length" "2")])
1250
1251 (define_split
1252   [(set (match_operand:SI 0 "register_operand" "")
1253         (eq:SI (match_operand:SI 1 "register_operand" "")
1254                (const_int 0)))
1255    (clobber (reg:CC 100))]
1256   ""
1257   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1258                                            (const_int 0)))
1259    (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
1260   "")
1261
1262 (define_insn "*neg_seqsi_zero"
1263   [(set (match_operand:SI 0 "register_operand" "=r")
1264         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1265                        (const_int 0))))
1266    (clobber (reg:CC 100))]
1267   "! TARGET_LIVE_G0"
1268   "#"
1269   [(set_attr "length" "2")])
1270
1271 (define_split
1272   [(set (match_operand:SI 0 "register_operand" "")
1273         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
1274                        (const_int 0))))
1275    (clobber (reg:CC 100))]
1276   ""
1277   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1278                                            (const_int 0)))
1279    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1280   "")
1281
1282 (define_insn "*seqsi_zero_extend"
1283   [(set (match_operand:DI 0 "register_operand" "=r")
1284         (eq:DI (match_operand:SI 1 "register_operand" "r")
1285                (const_int 0)))
1286    (clobber (reg:CC 100))]
1287   "TARGET_ARCH64"
1288   "#"
1289   [(set_attr "type" "unary")
1290    (set_attr "length" "2")])
1291
1292 (define_split
1293   [(set (match_operand:DI 0 "register_operand" "")
1294         (eq:DI (match_operand:SI 1 "register_operand" "")
1295                (const_int 0)))
1296    (clobber (reg:CC 100))]
1297   "TARGET_ARCH64"
1298   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
1299                                            (const_int 0)))
1300    (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
1301                                                           (const_int -1))
1302                                                 (ltu:SI (reg:CC_NOOV 100)
1303                                                         (const_int 0)))))]
1304   "")
1305
1306 (define_insn "*seqdi_zero"
1307   [(set (match_operand:DI 0 "register_operand" "=&r")
1308         (eq:DI (match_operand:DI 1 "register_operand" "r")
1309                (const_int 0)))]
1310   "TARGET_ARCH64"
1311   "#"
1312   [(set_attr "type" "cmove")
1313    (set_attr "length" "2")])
1314
1315 (define_split
1316   [(set (match_operand:DI 0 "register_operand" "")
1317         (eq:DI (match_operand:DI 1 "register_operand" "")
1318                (const_int 0)))]
1319   "TARGET_ARCH64"
1320   [(set (match_dup 0) (const_int 0))
1321    (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
1322                                               (const_int 0))
1323                                        (const_int 1)
1324                                        (match_dup 0)))]
1325   "")
1326
1327 (define_insn "*neg_seqdi_zero"
1328   [(set (match_operand:DI 0 "register_operand" "=&r")
1329         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
1330                        (const_int 0))))]
1331   "TARGET_ARCH64"
1332   "#"
1333   [(set_attr "type" "cmove")
1334    (set_attr "length" "2")]) 
1335
1336 (define_split
1337   [(set (match_operand:DI 0 "register_operand" "")
1338         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "")
1339                        (const_int 0))))]
1340   "TARGET_ARCH64"
1341   [(set (match_dup 0) (const_int 0))
1342    (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
1343                                               (const_int 0))
1344                                        (const_int -1)
1345                                        (match_dup 0)))]
1346   "")
1347
1348 (define_insn "*seqdi_zero_trunc"
1349   [(set (match_operand:SI 0 "register_operand" "=&r")
1350         (eq:SI (match_operand:DI 1 "register_operand" "r")
1351                (const_int 0)))]
1352   "TARGET_ARCH64"
1353   "#"
1354   [(set_attr "type" "cmove")
1355    (set_attr "length" "2")])
1356
1357 (define_split
1358   [(set (match_operand:SI 0 "register_operand" "")
1359         (eq:SI (match_operand:DI 1 "register_operand" "")
1360                (const_int 0)))]
1361   "TARGET_ARCH64"
1362   [(set (match_dup 0) (const_int 0))
1363    (set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
1364                                               (const_int 0))
1365                                        (const_int 1)
1366                                        (match_dup 0)))]
1367   "")
1368
1369 ;; We can also do (x + (i == 0)) and related, so put them in.
1370 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1371 ;; versions for v9.
1372
1373 (define_insn "*x_plus_i_ne_0"
1374   [(set (match_operand:SI 0 "register_operand" "=r")
1375         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
1376                         (const_int 0))
1377                  (match_operand:SI 2 "register_operand" "r")))
1378    (clobber (reg:CC 100))]
1379   "! TARGET_LIVE_G0"
1380   "#"
1381   [(set_attr "length" "2")])
1382
1383 (define_split
1384   [(set (match_operand:SI 0 "register_operand" "")
1385         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
1386                         (const_int 0))
1387                  (match_operand:SI 2 "register_operand" "")))
1388    (clobber (reg:CC 100))]
1389   "! TARGET_LIVE_G0"
1390   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1391                                            (const_int 0)))
1392    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1393                                (match_dup 2)))]
1394   "")
1395
1396 (define_insn "*x_minus_i_ne_0"
1397   [(set (match_operand:SI 0 "register_operand" "=r")
1398         (minus:SI (match_operand:SI 2 "register_operand" "r")
1399                   (ne:SI (match_operand:SI 1 "register_operand" "r")
1400                          (const_int 0))))
1401    (clobber (reg:CC 100))]
1402   "! TARGET_LIVE_G0"
1403   "#"
1404   [(set_attr "length" "2")])
1405
1406 (define_split
1407   [(set (match_operand:SI 0 "register_operand" "")
1408         (minus:SI (match_operand:SI 2 "register_operand" "")
1409                   (ne:SI (match_operand:SI 1 "register_operand" "")
1410                          (const_int 0))))
1411    (clobber (reg:CC 100))]
1412   "! TARGET_LIVE_G0"
1413   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1414                                            (const_int 0)))
1415    (set (match_dup 0) (minus:SI (match_dup 2)
1416                                 (ltu:SI (reg:CC 100) (const_int 0))))]
1417   "")
1418
1419 (define_insn "*x_plus_i_eq_0"
1420   [(set (match_operand:SI 0 "register_operand" "=r")
1421         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1422                         (const_int 0))
1423                  (match_operand:SI 2 "register_operand" "r")))
1424    (clobber (reg:CC 100))]
1425   "! TARGET_LIVE_G0"
1426   "#"
1427   [(set_attr "length" "2")])
1428
1429 (define_split
1430   [(set (match_operand:SI 0 "register_operand" "")
1431         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
1432                         (const_int 0))
1433                  (match_operand:SI 2 "register_operand" "")))
1434    (clobber (reg:CC 100))]
1435   "! TARGET_LIVE_G0"
1436   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1437                                            (const_int 0)))
1438    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1439                                (match_dup 2)))]
1440   "")
1441
1442 (define_insn "*x_minus_i_eq_0"
1443   [(set (match_operand:SI 0 "register_operand" "=r")
1444         (minus:SI (match_operand:SI 2 "register_operand" "r")
1445                   (eq:SI (match_operand:SI 1 "register_operand" "r")
1446                          (const_int 0))))
1447    (clobber (reg:CC 100))]
1448   "! TARGET_LIVE_G0"
1449   "#"
1450   [(set_attr "length" "2")])
1451
1452 (define_split
1453   [(set (match_operand:SI 0 "register_operand" "")
1454         (minus:SI (match_operand:SI 2 "register_operand" "")
1455                   (eq:SI (match_operand:SI 1 "register_operand" "")
1456                          (const_int 0))))
1457    (clobber (reg:CC 100))]
1458   "! TARGET_LIVE_G0"
1459   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1460                                            (const_int 0)))
1461    (set (match_dup 0) (minus:SI (match_dup 2)
1462                                 (geu:SI (reg:CC 100) (const_int 0))))]
1463   "")
1464
1465 ;; We can also do GEU and LTU directly, but these operate after a compare.
1466 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1467 ;; versions for v9.
1468
1469 (define_insn "*sltu_insn"
1470   [(set (match_operand:SI 0 "register_operand" "=r")
1471         (ltu:SI (reg:CC 100) (const_int 0)))]
1472   "! TARGET_LIVE_G0"
1473   "addx\\t%%g0, 0, %0"
1474   [(set_attr "type" "misc")
1475    (set_attr "length" "1")])
1476
1477 (define_insn "*neg_sltu_insn"
1478   [(set (match_operand:SI 0 "register_operand" "=r")
1479         (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1480   "! TARGET_LIVE_G0"
1481   "subx\\t%%g0, 0, %0"
1482   [(set_attr "type" "misc")
1483    (set_attr "length" "1")])
1484
1485 ;; ??? Combine should canonicalize these next two to the same pattern.
1486 (define_insn "*neg_sltu_minus_x"
1487   [(set (match_operand:SI 0 "register_operand" "=r")
1488         (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1489                   (match_operand:SI 1 "arith_operand" "rI")))]
1490   "! TARGET_LIVE_G0"
1491   "subx\\t%%g0, %1, %0"
1492   [(set_attr "type" "misc")
1493    (set_attr "length" "1")])
1494
1495 (define_insn "*neg_sltu_plus_x"
1496   [(set (match_operand:SI 0 "register_operand" "=r")
1497         (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1498                          (match_operand:SI 1 "arith_operand" "rI"))))]
1499   "! TARGET_LIVE_G0"
1500   "subx\\t%%g0, %1, %0"
1501   [(set_attr "type" "misc")
1502    (set_attr "length" "1")])
1503
1504 (define_insn "*sgeu_insn"
1505   [(set (match_operand:SI 0 "register_operand" "=r")
1506         (geu:SI (reg:CC 100) (const_int 0)))]
1507   "! TARGET_LIVE_G0"
1508   "subx\\t%%g0, -1, %0"
1509   [(set_attr "type" "misc")
1510    (set_attr "length" "1")])
1511
1512 (define_insn "*neg_sgeu_insn"
1513   [(set (match_operand:SI 0 "register_operand" "=r")
1514         (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1515   "! TARGET_LIVE_G0"
1516   "addx\\t%%g0, -1, %0"
1517   [(set_attr "type" "misc")
1518    (set_attr "length" "1")])
1519
1520 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1521 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1522 ;; versions for v9.
1523
1524 (define_insn "*sltu_plus_x"
1525   [(set (match_operand:SI 0 "register_operand" "=r")
1526         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1527                  (match_operand:SI 1 "arith_operand" "rI")))]
1528   "! TARGET_LIVE_G0"
1529   "addx\\t%%g0, %1, %0"
1530   [(set_attr "type" "misc")
1531    (set_attr "length" "1")])
1532
1533 (define_insn "*sltu_plus_x_plus_y"
1534   [(set (match_operand:SI 0 "register_operand" "=r")
1535         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1536                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1537                           (match_operand:SI 2 "arith_operand" "rI"))))]
1538   ""
1539   "addx\\t%1, %2, %0"
1540   [(set_attr "type" "misc")
1541    (set_attr "length" "1")])
1542
1543 (define_insn "*x_minus_sltu"
1544   [(set (match_operand:SI 0 "register_operand" "=r")
1545         (minus:SI (match_operand:SI 1 "register_operand" "r")
1546                   (ltu:SI (reg:CC 100) (const_int 0))))]
1547   ""
1548   "subx\\t%1, 0, %0"
1549   [(set_attr "type" "misc")
1550    (set_attr "length" "1")])
1551
1552 ;; ??? Combine should canonicalize these next two to the same pattern.
1553 (define_insn "*x_minus_y_minus_sltu"
1554   [(set (match_operand:SI 0 "register_operand" "=r")
1555         (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1556                             (match_operand:SI 2 "arith_operand" "rI"))
1557                   (ltu:SI (reg:CC 100) (const_int 0))))]
1558   ""
1559   "subx\\t%r1, %2, %0"
1560   [(set_attr "type" "misc")
1561    (set_attr "length" "1")])
1562
1563 (define_insn "*x_minus_sltu_plus_y"
1564   [(set (match_operand:SI 0 "register_operand" "=r")
1565         (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1566                   (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1567                            (match_operand:SI 2 "arith_operand" "rI"))))]
1568   ""
1569   "subx\\t%r1, %2, %0"
1570   [(set_attr "type" "misc")
1571    (set_attr "length" "1")])
1572
1573 (define_insn "*sgeu_plus_x"
1574   [(set (match_operand:SI 0 "register_operand" "=r")
1575         (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1576                  (match_operand:SI 1 "register_operand" "r")))]
1577   ""
1578   "subx\\t%1, -1, %0"
1579   [(set_attr "type" "misc")
1580    (set_attr "length" "1")])
1581
1582 (define_insn "*x_minus_sgeu"
1583   [(set (match_operand:SI 0 "register_operand" "=r")
1584         (minus:SI (match_operand:SI 1 "register_operand" "r")
1585                   (geu:SI (reg:CC 100) (const_int 0))))]
1586   ""
1587   "addx\\t%1, -1, %0"
1588   [(set_attr "type" "misc")
1589    (set_attr "length" "1")])
1590
1591 (define_split
1592   [(set (match_operand:SI 0 "register_operand" "=r")
1593         (match_operator:SI 2 "noov_compare_op"
1594                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1595                             (const_int 0)]))]
1596   ;; 32 bit LTU/GEU are better implemented using addx/subx
1597   "TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG
1598    && (GET_MODE (operands[1]) == CCXmode
1599        || (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))"
1600   [(set (match_dup 0) (const_int 0))
1601    (set (match_dup 0)
1602         (if_then_else:SI (match_op_dup:SI 2 [(match_dup 1) (const_int 0)])
1603                          (const_int 1)
1604                          (match_dup 0)))]
1605   "")
1606
1607 \f
1608 ;; These control RTL generation for conditional jump insns
1609
1610 ;; The quad-word fp compare library routines all return nonzero to indicate
1611 ;; true, which is different from the equivalent libgcc routines, so we must
1612 ;; handle them specially here.
1613
1614 (define_expand "beq"
1615   [(set (pc)
1616         (if_then_else (eq (match_dup 1) (const_int 0))
1617                       (label_ref (match_operand 0 "" ""))
1618                       (pc)))]
1619   ""
1620   "
1621 {
1622   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1623       && GET_CODE (sparc_compare_op0) == REG
1624       && GET_MODE (sparc_compare_op0) == DImode)
1625     {
1626       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1627       DONE;
1628     }
1629   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1630     {
1631       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1632       emit_jump_insn (gen_bne (operands[0]));
1633       DONE;
1634     }
1635   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1636 }")
1637
1638 (define_expand "bne"
1639   [(set (pc)
1640         (if_then_else (ne (match_dup 1) (const_int 0))
1641                       (label_ref (match_operand 0 "" ""))
1642                       (pc)))]
1643   ""
1644   "
1645 {
1646   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1647       && GET_CODE (sparc_compare_op0) == REG
1648       && GET_MODE (sparc_compare_op0) == DImode)
1649     {
1650       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1651       DONE;
1652     }
1653   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1654     {
1655       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1656       emit_jump_insn (gen_bne (operands[0]));
1657       DONE;
1658     }
1659   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1660 }")
1661
1662 (define_expand "bgt"
1663   [(set (pc)
1664         (if_then_else (gt (match_dup 1) (const_int 0))
1665                       (label_ref (match_operand 0 "" ""))
1666                       (pc)))]
1667   ""
1668   "
1669 {
1670   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1671       && GET_CODE (sparc_compare_op0) == REG
1672       && GET_MODE (sparc_compare_op0) == DImode)
1673     {
1674       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1675       DONE;
1676     }
1677   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1678     {
1679       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1680       emit_jump_insn (gen_bne (operands[0]));
1681       DONE;
1682     }
1683   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1684 }")
1685
1686 (define_expand "bgtu"
1687   [(set (pc)
1688         (if_then_else (gtu (match_dup 1) (const_int 0))
1689                       (label_ref (match_operand 0 "" ""))
1690                       (pc)))]
1691   ""
1692   "
1693 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1694 }")
1695
1696 (define_expand "blt"
1697   [(set (pc)
1698         (if_then_else (lt (match_dup 1) (const_int 0))
1699                       (label_ref (match_operand 0 "" ""))
1700                       (pc)))]
1701   ""
1702   "
1703 {
1704   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1705       && GET_CODE (sparc_compare_op0) == REG
1706       && GET_MODE (sparc_compare_op0) == DImode)
1707     {
1708       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1709       DONE;
1710     }
1711   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1712     {
1713       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1714       emit_jump_insn (gen_bne (operands[0]));
1715       DONE;
1716     }
1717   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1718 }")
1719
1720 (define_expand "bltu"
1721   [(set (pc)
1722         (if_then_else (ltu (match_dup 1) (const_int 0))
1723                       (label_ref (match_operand 0 "" ""))
1724                       (pc)))]
1725   ""
1726   "
1727 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1728 }")
1729
1730 (define_expand "bge"
1731   [(set (pc)
1732         (if_then_else (ge (match_dup 1) (const_int 0))
1733                       (label_ref (match_operand 0 "" ""))
1734                       (pc)))]
1735   ""
1736   "
1737 {
1738   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1739       && GET_CODE (sparc_compare_op0) == REG
1740       && GET_MODE (sparc_compare_op0) == DImode)
1741     {
1742       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1743       DONE;
1744     }
1745   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1746     {
1747       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1748       emit_jump_insn (gen_bne (operands[0]));
1749       DONE;
1750     }
1751   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1752 }")
1753
1754 (define_expand "bgeu"
1755   [(set (pc)
1756         (if_then_else (geu (match_dup 1) (const_int 0))
1757                       (label_ref (match_operand 0 "" ""))
1758                       (pc)))]
1759   ""
1760   "
1761 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1762 }")
1763
1764 (define_expand "ble"
1765   [(set (pc)
1766         (if_then_else (le (match_dup 1) (const_int 0))
1767                       (label_ref (match_operand 0 "" ""))
1768                       (pc)))]
1769   ""
1770   "
1771 {
1772   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1773       && GET_CODE (sparc_compare_op0) == REG
1774       && GET_MODE (sparc_compare_op0) == DImode)
1775     {
1776       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1777       DONE;
1778     }
1779   else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1780     {
1781       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1782       emit_jump_insn (gen_bne (operands[0]));
1783       DONE;
1784     }
1785   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1786 }")
1787
1788 (define_expand "bleu"
1789   [(set (pc)
1790         (if_then_else (leu (match_dup 1) (const_int 0))
1791                       (label_ref (match_operand 0 "" ""))
1792                       (pc)))]
1793   ""
1794   "
1795 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1796 }")
1797
1798 (define_expand "bunordered"
1799   [(set (pc)
1800         (if_then_else (unordered (match_dup 1) (const_int 0))
1801                       (label_ref (match_operand 0 "" ""))
1802                       (pc)))]
1803   ""
1804   "
1805 {
1806   if (GET_MODE (sparc_compare_op0) == TFmode
1807       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1808     {
1809       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
1810                                 UNORDERED);
1811       emit_jump_insn (gen_bne (operands[0]));
1812       DONE;
1813     }
1814   operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
1815                                  sparc_compare_op1);
1816 }")
1817
1818 (define_expand "bordered"
1819   [(set (pc)
1820         (if_then_else (ordered (match_dup 1) (const_int 0))
1821                       (label_ref (match_operand 0 "" ""))
1822                       (pc)))]
1823   ""
1824   "
1825 {
1826   if (GET_MODE (sparc_compare_op0) == TFmode
1827       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1828     {
1829       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
1830       emit_jump_insn (gen_bne (operands[0]));
1831       DONE;
1832     }
1833   operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
1834                                  sparc_compare_op1);
1835 }")
1836
1837 (define_expand "bungt"
1838   [(set (pc)
1839         (if_then_else (ungt (match_dup 1) (const_int 0))
1840                       (label_ref (match_operand 0 "" ""))
1841                       (pc)))]
1842   ""
1843   "
1844 {
1845   if (GET_MODE (sparc_compare_op0) == TFmode
1846       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1847     {
1848       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
1849       emit_jump_insn (gen_bne (operands[0]));
1850       DONE;
1851     }
1852   operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
1853 }")
1854
1855 (define_expand "bunlt"
1856   [(set (pc)
1857         (if_then_else (unlt (match_dup 1) (const_int 0))
1858                       (label_ref (match_operand 0 "" ""))
1859                       (pc)))]
1860   ""
1861   "
1862 {
1863   if (GET_MODE (sparc_compare_op0) == TFmode
1864       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1865     {
1866       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
1867       emit_jump_insn (gen_bne (operands[0]));
1868       DONE;
1869     }
1870   operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
1871 }")
1872
1873 (define_expand "buneq"
1874   [(set (pc)
1875         (if_then_else (uneq (match_dup 1) (const_int 0))
1876                       (label_ref (match_operand 0 "" ""))
1877                       (pc)))]
1878   ""
1879   "
1880 {
1881   if (GET_MODE (sparc_compare_op0) == TFmode
1882       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1883     {
1884       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
1885       emit_jump_insn (gen_bne (operands[0]));
1886       DONE;
1887     }
1888   operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
1889 }")
1890
1891 (define_expand "bunge"
1892   [(set (pc)
1893         (if_then_else (unge (match_dup 1) (const_int 0))
1894                       (label_ref (match_operand 0 "" ""))
1895                       (pc)))]
1896   ""
1897   "
1898 {
1899   if (GET_MODE (sparc_compare_op0) == TFmode
1900       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1901     {
1902       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
1903       emit_jump_insn (gen_bne (operands[0]));
1904       DONE;
1905     }
1906   operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
1907 }")
1908
1909 (define_expand "bunle"
1910   [(set (pc)
1911         (if_then_else (unle (match_dup 1) (const_int 0))
1912                       (label_ref (match_operand 0 "" ""))
1913                       (pc)))]
1914   ""
1915   "
1916 {
1917   if (GET_MODE (sparc_compare_op0) == TFmode
1918       && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
1919     {
1920       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
1921       emit_jump_insn (gen_bne (operands[0]));
1922       DONE;
1923     }
1924   operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
1925 }")
1926 \f
1927 ;; Now match both normal and inverted jump.
1928
1929 ;; XXX fpcmp nop braindamage
1930 (define_insn "*normal_branch"
1931   [(set (pc)
1932         (if_then_else (match_operator 0 "noov_compare_op"
1933                                       [(reg 100) (const_int 0)])
1934                       (label_ref (match_operand 1 "" ""))
1935                       (pc)))]
1936   ""
1937   "*
1938 {
1939   return output_cbranch (operands[0], 1, 0,
1940                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1941                          ! final_sequence, insn);
1942 }"
1943   [(set_attr "type" "branch")])
1944
1945 ;; XXX fpcmp nop braindamage
1946 (define_insn "*inverted_branch"
1947   [(set (pc)
1948         (if_then_else (match_operator 0 "noov_compare_op"
1949                                       [(reg 100) (const_int 0)])
1950                       (pc)
1951                       (label_ref (match_operand 1 "" ""))))]
1952   ""
1953   "*
1954 {
1955   return output_cbranch (operands[0], 1, 1,
1956                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1957                          ! final_sequence, insn);
1958 }"
1959   [(set_attr "type" "branch")])
1960
1961 ;; XXX fpcmp nop braindamage
1962 (define_insn "*normal_fp_branch"
1963   [(set (pc)
1964         (if_then_else (match_operator 1 "comparison_operator"
1965                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1966                                        (const_int 0)])
1967                       (label_ref (match_operand 2 "" ""))
1968                       (pc)))]
1969   ""
1970   "*
1971 {
1972   return output_cbranch (operands[1], 2, 0,
1973                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1974                          ! final_sequence, insn);
1975 }"
1976   [(set_attr "type" "branch")])
1977
1978 ;; XXX fpcmp nop braindamage
1979 (define_insn "*inverted_fp_branch"
1980   [(set (pc)
1981         (if_then_else (match_operator 1 "comparison_operator"
1982                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1983                                        (const_int 0)])
1984                       (pc)
1985                       (label_ref (match_operand 2 "" ""))))]
1986   ""
1987   "*
1988 {
1989   return output_cbranch (operands[1], 2, 1,
1990                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1991                          ! final_sequence, insn);
1992 }"
1993   [(set_attr "type" "branch")])
1994
1995 ;; XXX fpcmp nop braindamage
1996 (define_insn "*normal_fpe_branch"
1997   [(set (pc)
1998         (if_then_else (match_operator 1 "comparison_operator"
1999                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
2000                                        (const_int 0)])
2001                       (label_ref (match_operand 2 "" ""))
2002                       (pc)))]
2003   ""
2004   "*
2005 {
2006   return output_cbranch (operands[1], 2, 0,
2007                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
2008                          ! final_sequence, insn);
2009 }"
2010   [(set_attr "type" "branch")])
2011
2012 ;; XXX fpcmp nop braindamage
2013 (define_insn "*inverted_fpe_branch"
2014   [(set (pc)
2015         (if_then_else (match_operator 1 "comparison_operator"
2016                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
2017                                        (const_int 0)])
2018                       (pc)
2019                       (label_ref (match_operand 2 "" ""))))]
2020   ""
2021   "*
2022 {
2023   return output_cbranch (operands[1], 2, 1,
2024                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
2025                          ! final_sequence, insn);
2026 }"
2027   [(set_attr "type" "branch")])
2028
2029 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
2030 ;; in the architecture.
2031
2032 ;; There are no 32 bit brreg insns.
2033
2034 ;; XXX
2035 (define_insn "*normal_int_branch_sp64"
2036   [(set (pc)
2037         (if_then_else (match_operator 0 "v9_regcmp_op"
2038                                       [(match_operand:DI 1 "register_operand" "r")
2039                                        (const_int 0)])
2040                       (label_ref (match_operand 2 "" ""))
2041                       (pc)))]
2042   "TARGET_ARCH64"
2043   "*
2044 {
2045   return output_v9branch (operands[0], 1, 2, 0,
2046                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
2047                           ! final_sequence, insn);
2048 }"
2049   [(set_attr "type" "branch")])
2050
2051 ;; XXX
2052 (define_insn "*inverted_int_branch_sp64"
2053   [(set (pc)
2054         (if_then_else (match_operator 0 "v9_regcmp_op"
2055                                       [(match_operand:DI 1 "register_operand" "r")
2056                                        (const_int 0)])
2057                       (pc)
2058                       (label_ref (match_operand 2 "" ""))))]
2059   "TARGET_ARCH64"
2060   "*
2061 {
2062   return output_v9branch (operands[0], 1, 2, 1,
2063                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
2064                           ! final_sequence, insn);
2065 }"
2066   [(set_attr "type" "branch")])
2067 \f
2068 ;; Load program counter insns.
2069
2070 (define_insn "get_pc"
2071   [(clobber (reg:SI 15))
2072    (set (match_operand 0 "register_operand" "=r")
2073         (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
2074   "flag_pic && REGNO (operands[0]) == 23"
2075   "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0"
2076   [(set_attr "length" "3")])
2077
2078 ;; Currently unused...
2079 ;; (define_insn "get_pc_via_rdpc"
2080 ;;   [(set (match_operand 0 "register_operand" "=r") (pc))]
2081 ;;   "TARGET_V9"
2082 ;;   "rd\\t%%pc, %0"
2083 ;;   [(set_attr "type" "move")])
2084
2085 \f
2086 ;; Move instructions
2087
2088 (define_expand "movqi"
2089   [(set (match_operand:QI 0 "general_operand" "")
2090         (match_operand:QI 1 "general_operand" ""))]
2091   ""
2092   "
2093 {
2094   /* Working with CONST_INTs is easier, so convert
2095      a double if needed.  */
2096   if (GET_CODE (operands[1]) == CONST_DOUBLE)
2097     {
2098       operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xff);
2099     }
2100   else if (GET_CODE (operands[1]) == CONST_INT)
2101     {
2102       /* And further, we know for all QI cases that only the
2103          low byte is significant, which we can always process
2104          in a single insn.  So mask it now.  */
2105       operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
2106     }
2107
2108   /* Handle sets of MEM first.  */
2109   if (GET_CODE (operands[0]) == MEM)
2110     {
2111       /* This checks TARGET_LIVE_G0 for us.  */
2112       if (reg_or_0_operand (operands[1], QImode))
2113         goto movqi_is_ok;
2114
2115       if (! reload_in_progress)
2116         {
2117           operands[0] = validize_mem (operands[0]);
2118           operands[1] = force_reg (QImode, operands[1]);
2119         }
2120     }
2121
2122   /* Fixup PIC cases.  */
2123   if (flag_pic)
2124     {
2125       if (CONSTANT_P (operands[1])
2126           && pic_address_needs_scratch (operands[1]))
2127         operands[1] = legitimize_pic_address (operands[1], QImode, 0);
2128
2129       if (symbolic_operand (operands[1], QImode))
2130         {
2131           operands[1] = legitimize_pic_address (operands[1],
2132                                                 QImode,
2133                                                 (reload_in_progress ?
2134                                                  operands[0] :
2135                                                  NULL_RTX));
2136           goto movqi_is_ok;
2137         }
2138     }
2139
2140   /* All QI constants require only one insn, so proceed.  */
2141
2142  movqi_is_ok:
2143   ;
2144 }")
2145
2146 (define_insn "*movqi_insn"
2147   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
2148         (match_operand:QI 1 "input_operand"   "rI,m,rJ"))]
2149   "(register_operand (operands[0], QImode)
2150     || reg_or_0_operand (operands[1], QImode))"
2151   "@
2152    mov\\t%1, %0
2153    ldub\\t%1, %0
2154    stb\\t%r1, %0"
2155   [(set_attr "type" "move,load,store")
2156    (set_attr "length" "1")])
2157
2158 (define_expand "movhi"
2159   [(set (match_operand:HI 0 "general_operand" "")
2160         (match_operand:HI 1 "general_operand" ""))]
2161   ""
2162   "
2163 {
2164   /* Working with CONST_INTs is easier, so convert
2165      a double if needed.  */
2166   if (GET_CODE (operands[1]) == CONST_DOUBLE)
2167     operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
2168
2169   /* Handle sets of MEM first.  */
2170   if (GET_CODE (operands[0]) == MEM)
2171     {
2172       /* This checks TARGET_LIVE_G0 for us.  */
2173       if (reg_or_0_operand (operands[1], HImode))
2174         goto movhi_is_ok;
2175
2176       if (! reload_in_progress)
2177         {
2178           operands[0] = validize_mem (operands[0]);
2179           operands[1] = force_reg (HImode, operands[1]);
2180         }
2181     }
2182
2183   /* Fixup PIC cases.  */
2184   if (flag_pic)
2185     {
2186       if (CONSTANT_P (operands[1])
2187           && pic_address_needs_scratch (operands[1]))
2188         operands[1] = legitimize_pic_address (operands[1], HImode, 0);
2189
2190       if (symbolic_operand (operands[1], HImode))
2191         {
2192           operands[1] = legitimize_pic_address (operands[1],
2193                                                 HImode,
2194                                                 (reload_in_progress ?
2195                                                  operands[0] :
2196                                                  NULL_RTX));
2197           goto movhi_is_ok;
2198         }
2199     }
2200
2201   /* This makes sure we will not get rematched due to splittage. */
2202   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
2203     ;
2204   else if (CONSTANT_P (operands[1])
2205            && GET_CODE (operands[1]) != HIGH
2206            && GET_CODE (operands[1]) != LO_SUM)
2207     {
2208       sparc_emit_set_const32 (operands[0], operands[1]);
2209       DONE;
2210     }
2211  movhi_is_ok:
2212   ;
2213 }")
2214
2215 (define_insn "*movhi_const64_special"
2216   [(set (match_operand:HI 0 "register_operand" "=r")
2217         (match_operand:HI 1 "const64_high_operand" ""))]
2218   "TARGET_ARCH64"
2219   "sethi\\t%%hi(%a1), %0"
2220   [(set_attr "type" "move")
2221    (set_attr "length" "1")])
2222
2223 (define_insn "*movhi_insn"
2224   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
2225         (match_operand:HI 1 "input_operand"   "rI,K,m,rJ"))]
2226   "(register_operand (operands[0], HImode)
2227     || reg_or_0_operand (operands[1], HImode))"
2228   "@
2229    mov\\t%1, %0
2230    sethi\\t%%hi(%a1), %0
2231    lduh\\t%1, %0
2232    sth\\t%r1, %0"
2233   [(set_attr "type" "move,move,load,store")
2234    (set_attr "length" "1")])
2235
2236 ;; We always work with constants here.
2237 (define_insn "*movhi_lo_sum"
2238   [(set (match_operand:HI 0 "register_operand" "=r")
2239         (ior:HI (match_operand:HI 1 "arith_operand" "%r")
2240                 (match_operand:HI 2 "arith_operand" "I")))]
2241   ""
2242   "or\\t%1, %2, %0"
2243   [(set_attr "type" "ialu")
2244    (set_attr "length" "1")])
2245
2246 (define_expand "movsi"
2247   [(set (match_operand:SI 0 "general_operand" "")
2248         (match_operand:SI 1 "general_operand" ""))]
2249   ""
2250   "
2251 {
2252   /* Working with CONST_INTs is easier, so convert
2253      a double if needed.  */
2254   if (GET_CODE (operands[1]) == CONST_DOUBLE)
2255     operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
2256
2257   /* Handle sets of MEM first.  */
2258   if (GET_CODE (operands[0]) == MEM)
2259     {
2260       /* This checks TARGET_LIVE_G0 for us.  */
2261       if (reg_or_0_operand (operands[1], SImode))
2262         goto movsi_is_ok;
2263
2264       if (! reload_in_progress)
2265         {
2266           operands[0] = validize_mem (operands[0]);
2267           operands[1] = force_reg (SImode, operands[1]);
2268         }
2269     }
2270
2271   /* Fixup PIC cases.  */
2272   if (flag_pic)
2273     {
2274       if (CONSTANT_P (operands[1])
2275           && pic_address_needs_scratch (operands[1]))
2276         operands[1] = legitimize_pic_address (operands[1], SImode, 0);
2277
2278       if (GET_CODE (operands[1]) == LABEL_REF)
2279         {
2280           /* shit */
2281           emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
2282           DONE;
2283         }
2284
2285       if (symbolic_operand (operands[1], SImode))
2286         {
2287           operands[1] = legitimize_pic_address (operands[1],
2288                                                 SImode,
2289                                                 (reload_in_progress ?
2290                                                  operands[0] :
2291                                                  NULL_RTX));
2292           goto movsi_is_ok;
2293         }
2294     }
2295
2296   /* If we are trying to toss an integer constant into the
2297      FPU registers, force it into memory.  */
2298   if (GET_CODE (operands[0]) == REG
2299       && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
2300       && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
2301       && CONSTANT_P (operands[1]))
2302     operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2303                                                  operands[1]));
2304
2305   /* This makes sure we will not get rematched due to splittage. */
2306   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
2307     ;
2308   else if (CONSTANT_P (operands[1])
2309            && GET_CODE (operands[1]) != HIGH
2310            && GET_CODE (operands[1]) != LO_SUM)
2311     {
2312       sparc_emit_set_const32 (operands[0], operands[1]);
2313       DONE;
2314     }
2315  movsi_is_ok:
2316   ;
2317 }")
2318
2319 ;; Special LIVE_G0 pattern to obtain zero in a register.
2320 (define_insn "*movsi_zero_liveg0"
2321   [(set (match_operand:SI 0 "register_operand" "=r")
2322         (match_operand:SI 1 "zero_operand" "J"))]
2323   "TARGET_LIVE_G0"
2324   "and\\t%0, 0, %0"
2325   [(set_attr "type" "binary")
2326    (set_attr "length" "1")])
2327
2328 ;; This is needed to show CSE exactly which bits are set
2329 ;; in a 64-bit register by sethi instructions.
2330 (define_insn "*movsi_const64_special"
2331   [(set (match_operand:SI 0 "register_operand" "=r")
2332         (match_operand:SI 1 "const64_high_operand" ""))]
2333   "TARGET_ARCH64"
2334   "sethi\\t%%hi(%a1), %0"
2335   [(set_attr "type" "move")
2336    (set_attr "length" "1")])
2337
2338 (define_insn "*movsi_insn"
2339   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
2340         (match_operand:SI 1 "input_operand"   "rI,!f,K,J,m,!m,rJ,!f,J"))]
2341   "(register_operand (operands[0], SImode)
2342     || reg_or_0_operand (operands[1], SImode))"
2343   "@
2344    mov\\t%1, %0
2345    fmovs\\t%1, %0
2346    sethi\\t%%hi(%a1), %0
2347    clr\\t%0
2348    ld\\t%1, %0
2349    ld\\t%1, %0
2350    st\\t%r1, %0
2351    st\\t%1, %0
2352    fzeros\\t%0"
2353   [(set_attr "type" "move,fpmove,move,move,load,fpload,store,fpstore,fpmove")
2354    (set_attr "length" "1")])
2355
2356 (define_insn "*movsi_lo_sum"
2357   [(set (match_operand:SI 0 "register_operand" "=r")
2358         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
2359                    (match_operand:SI 2 "immediate_operand" "in")))]
2360   ""
2361   "or\\t%1, %%lo(%a2), %0"
2362   [(set_attr "type" "ialu")
2363    (set_attr "length" "1")])
2364
2365 (define_insn "*movsi_high"
2366   [(set (match_operand:SI 0 "register_operand" "=r")
2367         (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
2368   ""
2369   "sethi\\t%%hi(%a1), %0"
2370   [(set_attr "type" "move")
2371    (set_attr "length" "1")])
2372
2373 ;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
2374 ;; so that CSE won't optimize the address computation away.
2375 (define_insn "movsi_lo_sum_pic"
2376   [(set (match_operand:SI 0 "register_operand" "=r")
2377         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
2378                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
2379   "flag_pic"
2380   "or\\t%1, %%lo(%a2), %0"
2381   [(set_attr "type" "ialu")
2382    (set_attr "length" "1")])
2383
2384 (define_insn "movsi_high_pic"
2385   [(set (match_operand:SI 0 "register_operand" "=r")
2386         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
2387   "flag_pic && check_pic (1)"
2388   "sethi\\t%%hi(%a1), %0"
2389   [(set_attr "type" "move")
2390    (set_attr "length" "1")])
2391
2392 (define_expand "movsi_pic_label_ref"
2393   [(set (match_dup 3) (high:SI
2394      (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
2395                  (match_dup 2)] 5)))
2396    (set (match_dup 4) (lo_sum:SI (match_dup 3)
2397      (unspec:SI [(match_dup 1) (match_dup 2)] 5)))
2398    (set (match_operand:SI 0 "register_operand" "=r")
2399         (minus:SI (match_dup 5) (match_dup 4)))]
2400   "flag_pic"
2401   "
2402 {
2403   current_function_uses_pic_offset_table = 1;
2404   operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
2405   if (no_new_pseudos)
2406     {
2407       operands[3] = operands[0];
2408       operands[4] = operands[0];
2409     }
2410   else
2411     {
2412       operands[3] = gen_reg_rtx (SImode);
2413       operands[4] = gen_reg_rtx (SImode);
2414     }
2415   operands[5] = pic_offset_table_rtx;
2416 }")
2417
2418 (define_insn "*movsi_high_pic_label_ref"
2419   [(set (match_operand:SI 0 "register_operand" "=r")
2420       (high:SI
2421         (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
2422                     (match_operand:SI 2 "" "")] 5)))]
2423   "flag_pic"
2424   "sethi\\t%%hi(%a2-(%a1-.)), %0"
2425   [(set_attr "type" "move")
2426    (set_attr "length" "1")])
2427
2428 (define_insn "*movsi_lo_sum_pic_label_ref"
2429   [(set (match_operand:SI 0 "register_operand" "=r")
2430       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
2431         (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
2432                     (match_operand:SI 3 "" "")] 5)))]
2433   "flag_pic"
2434   "or\\t%1, %%lo(%a3-(%a2-.)), %0"
2435   [(set_attr "type" "ialu")
2436    (set_attr "length" "1")])
2437
2438 (define_expand "movdi"
2439   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
2440         (match_operand:DI 1 "general_operand" ""))]
2441   ""
2442   "
2443 {
2444   /* Where possible, convert CONST_DOUBLE into a CONST_INT.  */
2445   if (GET_CODE (operands[1]) == CONST_DOUBLE
2446 #if HOST_BITS_PER_WIDE_INT == 32
2447       && ((CONST_DOUBLE_HIGH (operands[1]) == 0
2448            && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
2449           || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
2450               && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
2451 #endif
2452       )
2453     operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
2454
2455   /* Handle MEM cases first.  */
2456   if (GET_CODE (operands[0]) == MEM)
2457     {
2458       /* If it's a REG, we can always do it.
2459          The const zero case is more complex, on v9
2460          we can always perform it.  */
2461       if (register_operand (operands[1], DImode)
2462           || (TARGET_ARCH64
2463               && (operands[1] == const0_rtx)))
2464         goto movdi_is_ok;
2465
2466       if (! reload_in_progress)
2467         {
2468           operands[0] = validize_mem (operands[0]);
2469           operands[1] = force_reg (DImode, operands[1]);
2470         }
2471     }
2472
2473   if (flag_pic)
2474     {
2475       if (CONSTANT_P (operands[1])
2476           && pic_address_needs_scratch (operands[1]))
2477         operands[1] = legitimize_pic_address (operands[1], DImode, 0);
2478
2479       if (GET_CODE (operands[1]) == LABEL_REF)
2480         {
2481           if (! TARGET_ARCH64)
2482             abort ();
2483           emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
2484           DONE;
2485         }
2486
2487       if (symbolic_operand (operands[1], DImode))
2488         {
2489           operands[1] = legitimize_pic_address (operands[1],
2490                                                 DImode,
2491                                                 (reload_in_progress ?
2492                                                  operands[0] :
2493                                                  NULL_RTX));
2494           goto movdi_is_ok;
2495         }
2496     }
2497
2498   /* If we are trying to toss an integer constant into the
2499      FPU registers, force it into memory.  */
2500   if (GET_CODE (operands[0]) == REG
2501       && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
2502       && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
2503       && CONSTANT_P (operands[1]))
2504     operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2505                                                  operands[1]));
2506
2507   /* This makes sure we will not get rematched due to splittage. */
2508   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
2509     ;
2510   else if (TARGET_ARCH64
2511            && CONSTANT_P (operands[1])
2512            && GET_CODE (operands[1]) != HIGH
2513            && GET_CODE (operands[1]) != LO_SUM)
2514     {
2515       sparc_emit_set_const64 (operands[0], operands[1]);
2516       DONE;
2517     }
2518
2519  movdi_is_ok:
2520   ;
2521 }")
2522
2523 ;; Be careful, fmovd does not exist when !arch64.
2524 ;; We match MEM moves directly when we have correct even
2525 ;; numbered registers, but fall into splits otherwise.
2526 ;; The constraint ordering here is really important to
2527 ;; avoid insane problems in reload, especially for patterns
2528 ;; of the form:
2529 ;;
2530 ;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
2531 ;;                       (const_int -5016)))
2532 ;;      (reg:DI 2 %g2))
2533 ;;
2534 (define_insn "*movdi_insn_sp32"
2535   [(set (match_operand:DI 0 "nonimmediate_operand" "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
2536         (match_operand:DI 1 "input_operand"    "U,T,r,o,i,r,f,T,o,f,f"))]
2537   "! TARGET_ARCH64 &&
2538    (register_operand (operands[0], DImode)
2539     || register_operand (operands[1], DImode))"
2540   "@
2541    std\\t%1, %0
2542    ldd\\t%1, %0
2543    #
2544    #
2545    #
2546    #
2547    std\\t%1, %0
2548    ldd\\t%1, %0
2549    #
2550    #
2551    #"
2552   [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
2553    (set_attr "length" "1,1,2,2,2,2,1,1,2,2,2")])
2554
2555 ;; The following are generated by sparc_emit_set_const64
2556 (define_insn "*movdi_sp64_dbl"
2557   [(set (match_operand:DI 0 "register_operand" "=r")
2558         (match_operand:DI 1 "const64_operand" ""))]
2559   "(TARGET_ARCH64
2560     && HOST_BITS_PER_WIDE_INT != 64)"
2561   "mov\\t%1, %0"
2562   [(set_attr "type" "move")
2563    (set_attr "length" "1")])
2564
2565 ;; This is needed to show CSE exactly which bits are set
2566 ;; in a 64-bit register by sethi instructions.
2567 (define_insn "*movdi_const64_special"
2568   [(set (match_operand:DI 0 "register_operand" "=r")
2569         (match_operand:DI 1 "const64_high_operand" ""))]
2570   "TARGET_ARCH64"
2571   "sethi\\t%%hi(%a1), %0"
2572   [(set_attr "type" "move")
2573    (set_attr "length" "1")])
2574
2575 (define_insn "*movdi_insn_sp64"
2576   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m,b")
2577         (match_operand:DI 1 "input_operand"   "rI,K,J,m,rJ,e,m,e,J"))]
2578   "TARGET_ARCH64 &&
2579    (register_operand (operands[0], DImode)
2580     || reg_or_0_operand (operands[1], DImode))"
2581   "@
2582    mov\\t%1, %0
2583    sethi\\t%%hi(%a1), %0
2584    clr\\t%0
2585    ldx\\t%1, %0
2586    stx\\t%r1, %0
2587    fmovd\\t%1, %0
2588    ldd\\t%1, %0
2589    std\\t%1, %0
2590    fzero\\t%0"
2591   [(set_attr "type" "move,move,move,load,store,fpmove,fpload,fpstore,fpmove")
2592    (set_attr "length" "1")])
2593
2594 (define_expand "movdi_pic_label_ref"
2595   [(set (match_dup 3) (high:DI
2596      (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2597                  (match_dup 2)] 5)))
2598    (set (match_dup 4) (lo_sum:DI (match_dup 3)
2599      (unspec:DI [(match_dup 1) (match_dup 2)] 5)))
2600    (set (match_operand:DI 0 "register_operand" "=r")
2601         (minus:DI (match_dup 5) (match_dup 4)))]
2602   "TARGET_ARCH64 && flag_pic"
2603   "
2604 {
2605   current_function_uses_pic_offset_table = 1;
2606   operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
2607   if (no_new_pseudos)
2608     {
2609       operands[3] = operands[0];
2610       operands[4] = operands[0];
2611     }
2612   else
2613     {
2614       operands[3] = gen_reg_rtx (DImode);
2615       operands[4] = gen_reg_rtx (DImode);
2616     }
2617   operands[5] = pic_offset_table_rtx;
2618 }")
2619
2620 (define_insn "*movdi_high_pic_label_ref"
2621   [(set (match_operand:DI 0 "register_operand" "=r")
2622         (high:DI
2623           (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2624                       (match_operand:DI 2 "" "")] 5)))]
2625   "TARGET_ARCH64 && flag_pic"
2626   "sethi\\t%%hi(%a2-(%a1-.)), %0"
2627   [(set_attr "type" "move")
2628    (set_attr "length" "1")])
2629
2630 (define_insn "*movdi_lo_sum_pic_label_ref"
2631   [(set (match_operand:DI 0 "register_operand" "=r")
2632       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2633         (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2634                     (match_operand:DI 3 "" "")] 5)))]
2635   "TARGET_ARCH64 && flag_pic"
2636   "or\\t%1, %%lo(%a3-(%a2-.)), %0"
2637   [(set_attr "type" "ialu")
2638    (set_attr "length" "1")])
2639
2640 ;; Sparc-v9 code model support insns.  See sparc_emit_set_symbolic_const64
2641 ;; in sparc.c to see what is going on here... PIC stuff comes first.
2642
2643 (define_insn "movdi_lo_sum_pic"
2644   [(set (match_operand:DI 0 "register_operand" "=r")
2645         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2646                    (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
2647   "TARGET_ARCH64 && flag_pic"
2648   "or\\t%1, %%lo(%a2), %0"
2649   [(set_attr "type" "ialu")
2650    (set_attr "length" "1")])
2651
2652 (define_insn "movdi_high_pic"
2653   [(set (match_operand:DI 0 "register_operand" "=r")
2654         (high:DI (unspec:DI [(match_operand 1 "" "")] 0)))]
2655   "TARGET_ARCH64 && flag_pic && check_pic (1)"
2656   "sethi\\t%%hi(%a1), %0"
2657   [(set_attr "type" "move")
2658    (set_attr "length" "1")])
2659
2660 (define_insn "*sethi_di_medlow_embmedany_pic"
2661   [(set (match_operand:DI 0 "register_operand" "=r")
2662         (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
2663   "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2664   "sethi\\t%%hi(%a1), %0"
2665   [(set_attr "type" "move")
2666    (set_attr "length" "1")])
2667
2668 (define_insn "*sethi_di_medlow"
2669   [(set (match_operand:DI 0 "register_operand" "=r")
2670         (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2671   "TARGET_CM_MEDLOW && check_pic (1)"
2672   "sethi\\t%%hi(%a1), %0"
2673   [(set_attr "type" "move")
2674    (set_attr "length" "1")])
2675
2676 (define_insn "*losum_di_medlow"
2677   [(set (match_operand:DI 0 "register_operand" "=r")
2678         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2679                    (match_operand:DI 2 "symbolic_operand" "")))]
2680   "TARGET_CM_MEDLOW"
2681   "or\\t%1, %%lo(%a2), %0"
2682   [(set_attr "type" "ialu")
2683    (set_attr "length" "1")])
2684
2685 (define_insn "seth44"
2686   [(set (match_operand:DI 0 "register_operand" "=r")
2687         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 6)))]
2688   "TARGET_CM_MEDMID"
2689   "sethi\\t%%h44(%a1), %0"
2690   [(set_attr "type" "move")
2691    (set_attr "length" "1")])
2692
2693 (define_insn "setm44"
2694   [(set (match_operand:DI 0 "register_operand" "=r")
2695         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2696                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 7)))]
2697   "TARGET_CM_MEDMID"
2698   "or\\t%1, %%m44(%a2), %0"
2699   [(set_attr "type" "move")
2700    (set_attr "length" "1")])
2701
2702 (define_insn "setl44"
2703   [(set (match_operand:DI 0 "register_operand" "=r")
2704         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2705                    (match_operand:DI 2 "symbolic_operand" "")))]
2706   "TARGET_CM_MEDMID"
2707   "or\\t%1, %%l44(%a2), %0"
2708   [(set_attr "type" "ialu")
2709    (set_attr "length" "1")])
2710
2711 (define_insn "sethh"
2712   [(set (match_operand:DI 0 "register_operand" "=r")
2713         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 9)))]
2714   "TARGET_CM_MEDANY"
2715   "sethi\\t%%hh(%a1), %0"
2716   [(set_attr "type" "move")
2717    (set_attr "length" "1")])
2718
2719 (define_insn "setlm"
2720   [(set (match_operand:DI 0 "register_operand" "=r")
2721         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 10)))]
2722   "TARGET_CM_MEDANY"
2723   "sethi\\t%%lm(%a1), %0"
2724   [(set_attr "type" "move")
2725    (set_attr "length" "1")])
2726
2727 (define_insn "sethm"
2728   [(set (match_operand:DI 0 "register_operand" "=r")
2729         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2730                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 18)))]
2731   "TARGET_CM_MEDANY"
2732   "or\\t%1, %%hm(%a2), %0"
2733   [(set_attr "type" "ialu")
2734    (set_attr "length" "1")])
2735
2736 (define_insn "setlo"
2737   [(set (match_operand:DI 0 "register_operand" "=r")
2738         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2739                    (match_operand:DI 2 "symbolic_operand" "")))]
2740   "TARGET_CM_MEDANY"
2741   "or\\t%1, %%lo(%a2), %0"
2742   [(set_attr "type" "ialu")
2743    (set_attr "length" "1")])
2744
2745 (define_insn "embmedany_sethi"
2746   [(set (match_operand:DI 0 "register_operand" "=r")
2747         (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] 11)))]
2748   "TARGET_CM_EMBMEDANY && check_pic (1)"
2749   "sethi\\t%%hi(%a1), %0"
2750   [(set_attr "type" "move")
2751    (set_attr "length" "1")])
2752
2753 (define_insn "embmedany_losum"
2754   [(set (match_operand:DI 0 "register_operand" "=r")
2755         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2756                    (match_operand:DI 2 "data_segment_operand" "")))]
2757   "TARGET_CM_EMBMEDANY"
2758   "add\\t%1, %%lo(%a2), %0"
2759   [(set_attr "type" "ialu")
2760    (set_attr "length" "1")])
2761
2762 (define_insn "embmedany_brsum"
2763   [(set (match_operand:DI 0 "register_operand" "=r")
2764         (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 11))]
2765   "TARGET_CM_EMBMEDANY"
2766   "add\\t%1, %_, %0"
2767   [(set_attr "length" "1")])
2768
2769 (define_insn "embmedany_textuhi"
2770   [(set (match_operand:DI 0 "register_operand" "=r")
2771         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 13)))]
2772   "TARGET_CM_EMBMEDANY && check_pic (1)"
2773   "sethi\\t%%uhi(%a1), %0"
2774   [(set_attr "type" "move")
2775    (set_attr "length" "1")])
2776
2777 (define_insn "embmedany_texthi"
2778   [(set (match_operand:DI 0 "register_operand" "=r")
2779         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 14)))]
2780   "TARGET_CM_EMBMEDANY && check_pic (1)"
2781   "sethi\\t%%hi(%a1), %0"
2782   [(set_attr "type" "move")
2783    (set_attr "length" "1")])
2784
2785 (define_insn "embmedany_textulo"
2786   [(set (match_operand:DI 0 "register_operand" "=r")
2787         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2788                    (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] 15)))]
2789   "TARGET_CM_EMBMEDANY"
2790   "or\\t%1, %%ulo(%a2), %0"
2791   [(set_attr "type" "ialu")
2792    (set_attr "length" "1")])
2793
2794 (define_insn "embmedany_textlo"
2795   [(set (match_operand:DI 0 "register_operand" "=r")
2796         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2797                    (match_operand:DI 2 "text_segment_operand" "")))]
2798   "TARGET_CM_EMBMEDANY"
2799   "or\\t%1, %%lo(%a2), %0"
2800   [(set_attr "type" "ialu")
2801    (set_attr "length" "1")])
2802
2803 ;; Now some patterns to help reload out a bit.
2804 (define_expand "reload_indi"
2805   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2806               (match_operand:DI 1 "immediate_operand" "")
2807               (match_operand:TI 2 "register_operand" "=&r")])]
2808   "(TARGET_CM_MEDANY
2809     || TARGET_CM_EMBMEDANY)
2810    && ! flag_pic"
2811   "
2812 {
2813   sparc_emit_set_symbolic_const64 (operands[0], operands[1],
2814                                    gen_rtx_REG (DImode, REGNO (operands[2])));
2815   DONE;
2816 }")
2817
2818 (define_expand "reload_outdi"
2819   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2820               (match_operand:DI 1 "immediate_operand" "")
2821               (match_operand:TI 2 "register_operand" "=&r")])]
2822   "(TARGET_CM_MEDANY
2823     || TARGET_CM_EMBMEDANY)
2824    && ! flag_pic"
2825   "
2826 {
2827   sparc_emit_set_symbolic_const64 (operands[0], operands[1],
2828                                    gen_rtx_REG (DImode, REGNO (operands[2])));
2829   DONE;
2830 }")
2831
2832 ;; Split up putting CONSTs and REGs into DI regs when !arch64
2833 (define_split
2834   [(set (match_operand:DI 0 "register_operand" "")
2835         (match_operand:DI 1 "const_int_operand" ""))]
2836   "! TARGET_ARCH64 && reload_completed"
2837   [(clobber (const_int 0))]
2838   "
2839 {
2840   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2841                         (INTVAL (operands[1]) < 0) ?
2842                         constm1_rtx :
2843                         const0_rtx));
2844   emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2845                         operands[1]));
2846   DONE;
2847 }")
2848
2849 (define_split
2850   [(set (match_operand:DI 0 "register_operand" "")
2851         (match_operand:DI 1 "const_double_operand" ""))]
2852   "! TARGET_ARCH64 && reload_completed"
2853   [(clobber (const_int 0))]
2854   "
2855 {
2856   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2857                         GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2858
2859   /* Slick... but this trick loses if this subreg constant part
2860      can be done in one insn.  */
2861   if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2862       && !(SPARC_SETHI_P (CONST_DOUBLE_HIGH (operands[1]))
2863            || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
2864     {
2865       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2866                             gen_highpart (SImode, operands[0])));
2867     }
2868   else
2869     {
2870       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2871                             GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2872     }
2873   DONE;
2874 }")
2875
2876 (define_split
2877   [(set (match_operand:DI 0 "register_operand" "")
2878         (match_operand:DI 1 "register_operand" ""))]
2879   "! TARGET_ARCH64 && reload_completed"
2880   [(clobber (const_int 0))]
2881   "
2882 {
2883   rtx set_dest = operands[0];
2884   rtx set_src = operands[1];
2885   rtx dest1, dest2;
2886   rtx src1, src2;
2887
2888   if (GET_CODE (set_dest) == SUBREG)
2889     set_dest = alter_subreg (set_dest);
2890   if (GET_CODE (set_src) == SUBREG)
2891     set_src = alter_subreg (set_src);
2892
2893   dest1 = gen_highpart (SImode, set_dest);
2894   dest2 = gen_lowpart (SImode, set_dest);
2895   src1 = gen_highpart (SImode, set_src);
2896   src2 = gen_lowpart (SImode, set_src);
2897
2898   /* Now emit using the real source and destination we found, swapping
2899      the order if we detect overlap.  */
2900   if (reg_overlap_mentioned_p (dest1, src2))
2901     {
2902       emit_insn (gen_movsi (dest2, src2));
2903       emit_insn (gen_movsi (dest1, src1));
2904     }
2905   else
2906     {
2907       emit_insn (gen_movsi (dest1, src1));
2908       emit_insn (gen_movsi (dest2, src2));
2909     }
2910   DONE;
2911 }")
2912
2913 ;; Now handle the cases of memory moves from/to non-even
2914 ;; DI mode register pairs.
2915 (define_split
2916   [(set (match_operand:DI 0 "register_operand" "")
2917         (match_operand:DI 1 "memory_operand" ""))]
2918   "(! TARGET_ARCH64
2919     && reload_completed
2920     && sparc_splitdi_legitimate (operands[0], operands[1]))"
2921   [(clobber (const_int 0))]
2922   "
2923 {
2924   rtx word0 = change_address (operands[1], SImode, NULL_RTX);
2925   rtx word1 = change_address (operands[1], SImode,
2926                               plus_constant_for_output (XEXP (word0, 0), 4));
2927   rtx high_part = gen_highpart (SImode, operands[0]);
2928   rtx low_part = gen_lowpart (SImode, operands[0]);
2929
2930   if (reg_overlap_mentioned_p (high_part, word1))
2931     {
2932       emit_insn (gen_movsi (low_part, word1));
2933       emit_insn (gen_movsi (high_part, word0));
2934     }
2935   else
2936     {
2937       emit_insn (gen_movsi (high_part, word0));
2938       emit_insn (gen_movsi (low_part, word1));
2939     }
2940   DONE;
2941 }")
2942
2943 (define_split
2944   [(set (match_operand:DI 0 "memory_operand" "")
2945         (match_operand:DI 1 "register_operand" ""))]
2946   "(! TARGET_ARCH64
2947     && reload_completed
2948     && sparc_splitdi_legitimate (operands[1], operands[0]))"
2949   [(clobber (const_int 0))]
2950   "
2951 {
2952   rtx word0 = change_address (operands[0], SImode, NULL_RTX);
2953   rtx word1 = change_address (operands[0], SImode,
2954                               plus_constant_for_output (XEXP (word0, 0), 4));
2955   rtx high_part = gen_highpart (SImode, operands[1]);
2956   rtx low_part = gen_lowpart (SImode, operands[1]);
2957
2958   emit_insn (gen_movsi (word0, high_part));
2959   emit_insn (gen_movsi (word1, low_part));
2960   DONE;
2961 }")
2962
2963 \f
2964 ;; Floating point move insns
2965
2966 (define_insn "*movsf_insn_novis_liveg0"
2967   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
2968         (match_operand:SF 1 "input_operand"         "f,G,Q,*rR,S,m,m,f,*r"))]
2969   "(TARGET_FPU && ! TARGET_VIS && TARGET_LIVE_G0)
2970    && (register_operand (operands[0], SFmode)
2971        || register_operand (operands[1], SFmode))"
2972   "*
2973 {
2974   if (GET_CODE (operands[1]) == CONST_DOUBLE
2975       && (which_alternative == 2
2976           || which_alternative == 3
2977           || which_alternative == 4))
2978     {
2979       REAL_VALUE_TYPE r;
2980       long i;
2981
2982       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2983       REAL_VALUE_TO_TARGET_SINGLE (r, i);
2984       operands[1] = GEN_INT (i);
2985     }
2986
2987   switch (which_alternative)
2988     {
2989     case 0:
2990       return \"fmovs\\t%1, %0\";
2991     case 1:
2992       return \"and\\t%0, 0, %0\";
2993     case 2:
2994       return \"sethi\\t%%hi(%a1), %0\";
2995     case 3:
2996       return \"mov\\t%1, %0\";
2997     case 4:
2998       return \"#\";
2999     case 5:
3000     case 6:
3001       return \"ld\\t%1, %0\";
3002     case 7:
3003     case 8:
3004       return \"st\\t%1, %0\";
3005     }
3006 }"
3007   [(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
3008    (set_attr "length" "1")])
3009
3010 (define_insn "*movsf_insn_novis_noliveg0"
3011   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
3012         (match_operand:SF 1 "input_operand"         "f,G,Q,*rR,S,m,m,f,*rG"))]
3013   "(TARGET_FPU && ! TARGET_VIS && ! TARGET_LIVE_G0)
3014    && (register_operand (operands[0], SFmode)
3015        || register_operand (operands[1], SFmode)
3016        || fp_zero_operand (operands[1]))"
3017   "*
3018 {
3019   if (GET_CODE (operands[1]) == CONST_DOUBLE
3020       && (which_alternative == 2
3021           || which_alternative == 3
3022           || which_alternative == 4))
3023     {
3024       REAL_VALUE_TYPE r;
3025       long i;
3026
3027       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3028       REAL_VALUE_TO_TARGET_SINGLE (r, i);
3029       operands[1] = GEN_INT (i);
3030     }
3031
3032   switch (which_alternative)
3033     {
3034     case 0:
3035       return \"fmovs\\t%1, %0\";
3036     case 1:
3037       return \"clr\\t%0\";
3038     case 2:
3039       return \"sethi\\t%%hi(%a1), %0\";
3040     case 3:
3041       return \"mov\\t%1, %0\";
3042     case 4:
3043       return \"#\";
3044     case 5:
3045     case 6:
3046       return \"ld\\t%1, %0\";
3047     case 7:
3048     case 8:
3049       return \"st\\t%r1, %0\";
3050     }
3051 }"
3052   [(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
3053    (set_attr "length" "1")])
3054
3055 (define_insn "*movsf_insn_vis"
3056   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
3057         (match_operand:SF 1 "input_operand"         "f,G,G,Q,*rR,S,m,m,f,*rG"))]
3058   "(TARGET_FPU && TARGET_VIS)
3059    && (register_operand (operands[0], SFmode)
3060        || register_operand (operands[1], SFmode)
3061        || fp_zero_operand (operands[1]))"
3062   "*
3063 {
3064   if (GET_CODE (operands[1]) == CONST_DOUBLE
3065       && (which_alternative == 3
3066           || which_alternative == 4
3067           || which_alternative == 5))
3068     {
3069       REAL_VALUE_TYPE r;
3070       long i;
3071
3072       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3073       REAL_VALUE_TO_TARGET_SINGLE (r, i);
3074       operands[1] = GEN_INT (i);
3075     }
3076
3077   switch (which_alternative)
3078     {
3079     case 0:
3080       return \"fmovs\\t%1, %0\";
3081     case 1:
3082       return \"fzeros\\t%0\";
3083     case 2:
3084       return \"clr\\t%0\";
3085     case 3:
3086       return \"sethi\\t%%hi(%a1), %0\";
3087     case 4:
3088       return \"mov\\t%1, %0\";
3089     case 5:
3090       return \"#\";
3091     case 6:
3092     case 7:
3093       return \"ld\\t%1, %0\";
3094     case 8:
3095     case 9:
3096       return \"st\\t%r1, %0\";
3097     }
3098 }"
3099   [(set_attr "type" "fpmove,fpmove,move,move,move,*,load,fpload,fpstore,store")
3100    (set_attr "length" "1")])
3101
3102 (define_insn "*movsf_lo_sum"
3103   [(set (match_operand:SF 0 "register_operand" "")
3104         (lo_sum:SF (match_operand:SF 1 "register_operand" "")
3105                    (match_operand:SF 2 "const_double_operand" "")))]
3106   "TARGET_FPU && fp_high_losum_p (operands[2])"
3107   "*
3108 {
3109   REAL_VALUE_TYPE r;
3110   long i;
3111
3112   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
3113   REAL_VALUE_TO_TARGET_SINGLE (r, i);
3114   operands[2] = GEN_INT (i);
3115   return \"or\\t%1, %%lo(%a2), %0\";
3116 }"
3117   [(set_attr "type" "ialu")
3118    (set_attr "length" "1")])
3119
3120 (define_insn "*movsf_high"
3121   [(set (match_operand:SF 0 "register_operand" "")
3122         (high:SF (match_operand:SF 1 "const_double_operand" "")))]
3123   "TARGET_FPU && fp_high_losum_p (operands[1])"
3124   "*
3125 {
3126   REAL_VALUE_TYPE r;
3127   long i;
3128
3129   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3130   REAL_VALUE_TO_TARGET_SINGLE (r, i);
3131   operands[1] = GEN_INT (i);
3132   return \"sethi\\t%%hi(%1), %0\";
3133 }"
3134   [(set_attr "type" "move")
3135    (set_attr "length" "1")])
3136
3137 (define_split
3138   [(set (match_operand:SF 0 "register_operand" "")
3139         (match_operand:SF 1 "const_double_operand" ""))]
3140   "TARGET_FPU
3141    && fp_high_losum_p (operands[1])
3142    && (GET_CODE (operands[0]) == REG
3143        && REGNO (operands[0]) < 32)"
3144   [(set (match_dup 0) (high:SF (match_dup 1)))
3145    (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
3146
3147 ;; Exactly the same as above, except that all `f' cases are deleted.
3148 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3149 ;; when -mno-fpu.
3150
3151 (define_insn "*movsf_no_f_insn"
3152   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
3153         (match_operand:SF 1 "input_operand"    "r,m,r"))]
3154   "! TARGET_FPU
3155    && (register_operand (operands[0], SFmode)
3156        || register_operand (operands[1], SFmode))"
3157   "@
3158    mov\\t%1, %0
3159    ld\\t%1, %0
3160    st\\t%1, %0"
3161   [(set_attr "type" "move,load,store")
3162    (set_attr "length" "1")])
3163
3164 (define_expand "movsf"
3165   [(set (match_operand:SF 0 "general_operand" "")
3166         (match_operand:SF 1 "general_operand" ""))]
3167   ""
3168   "
3169 {
3170   /* Force SFmode constants into memory.  */
3171   if (GET_CODE (operands[0]) == REG
3172       && CONSTANT_P (operands[1]))
3173     {
3174       if (TARGET_VIS
3175           && GET_CODE (operands[1]) == CONST_DOUBLE
3176           && fp_zero_operand (operands[1]))
3177         goto movsf_is_ok;
3178
3179       /* emit_group_store will send such bogosity to us when it is
3180          not storing directly into memory.  So fix this up to avoid
3181          crashes in output_constant_pool.  */
3182       if (operands [1] == const0_rtx)
3183         operands[1] = CONST0_RTX (SFmode);
3184       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3185                                                    operands[1]));
3186     }
3187
3188   /* Handle sets of MEM first.  */
3189   if (GET_CODE (operands[0]) == MEM)
3190     {
3191       if (register_operand (operands[1], SFmode)
3192           || (! TARGET_LIVE_G0
3193               && GET_CODE (operands[1]) == CONST_DOUBLE
3194               && fp_zero_operand (operands[1])))
3195         goto movsf_is_ok;
3196
3197       if (! reload_in_progress)
3198         {
3199           operands[0] = validize_mem (operands[0]);
3200           operands[1] = force_reg (SFmode, operands[1]);
3201         }
3202     }
3203
3204   /* Fixup PIC cases.  */
3205   if (flag_pic)
3206     {
3207       if (CONSTANT_P (operands[1])
3208           && pic_address_needs_scratch (operands[1]))
3209         operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
3210
3211       if (symbolic_operand (operands[1], SFmode))
3212         {
3213           operands[1] = legitimize_pic_address (operands[1],
3214                                                 SFmode,
3215                                                 (reload_in_progress ?
3216                                                  operands[0] :
3217                                                  NULL_RTX));
3218         }
3219     }
3220
3221  movsf_is_ok:
3222   ;
3223 }")
3224
3225 (define_insn "*clear_df"
3226   [(set (match_operand:DF 0 "register_operand" "=e")
3227         (match_operand:DF 1 "const_double_operand" ""))]
3228   "TARGET_VIS
3229    && fp_zero_operand (operands[1])"
3230   "fzero\\t%0"
3231   [(set_attr "type" "fpmove")
3232    (set_attr "length" "1")])
3233
3234 (define_insn "*clear_dfp"
3235   [(set (match_operand:DF 0 "memory_operand" "=m")
3236         (match_operand:DF 1 "const_double_operand" ""))]
3237   "! TARGET_LIVE_G0
3238    && TARGET_V9
3239    && fp_zero_operand (operands[1])"
3240   "stx\\t%%g0, %0"
3241   [(set_attr "type" "store")
3242    (set_attr "length" "1")])
3243
3244 (define_insn "*movdf_const_intreg_sp32"
3245   [(set (match_operand:DF 0 "register_operand" "=e,e,?r")
3246         (match_operand:DF 1 "const_double_operand" "T#F,o#F,F"))]
3247   "TARGET_FPU && ! TARGET_ARCH64"
3248   "@
3249    ldd\\t%1, %0
3250    #
3251    #"
3252   [(set_attr "type" "move")
3253    (set_attr "length" "1,2,2")])
3254
3255 ;; Now that we redo life analysis with a clean slate after
3256 ;; instruction splitting for sched2 this can work.
3257 (define_insn "*movdf_const_intreg_sp64"
3258   [(set (match_operand:DF 0 "register_operand" "=e,?r")
3259         (match_operand:DF 1 "const_double_operand" "m#F,F"))]
3260   "TARGET_FPU && TARGET_ARCH64"
3261   "@
3262    ldd\\t%1, %0
3263    #"
3264   [(set_attr "type" "move")
3265    (set_attr "length" "1,2")])
3266
3267 (define_split
3268   [(set (match_operand:DF 0 "register_operand" "")
3269         (match_operand:DF 1 "const_double_operand" ""))]
3270   "TARGET_FPU
3271    && (GET_CODE (operands[0]) == REG
3272        && REGNO (operands[0]) < 32)
3273    && reload_completed"
3274   [(clobber (const_int 0))]
3275   "
3276 {
3277   REAL_VALUE_TYPE r;
3278   long l[2];
3279
3280   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3281   REAL_VALUE_TO_TARGET_DOUBLE (r, l);
3282   if (GET_CODE (operands[0]) == SUBREG)
3283     operands[0] = alter_subreg (operands[0]);
3284   operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
3285
3286   if (TARGET_ARCH64)
3287     {
3288 #if HOST_BITS_PER_WIDE_INT == 64
3289       HOST_WIDE_INT val;
3290
3291       val = ((HOST_WIDE_INT)(unsigned long)l[1] |
3292              ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
3293       emit_insn (gen_movdi (operands[0], GEN_INT (val)));
3294 #else
3295       emit_insn (gen_movdi (operands[0],
3296                             gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
3297                                                   l[1], l[0])));
3298 #endif
3299     }
3300   else
3301     {
3302       emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
3303                             GEN_INT (l[0])));
3304
3305       /* Slick... but this trick loses if this subreg constant part
3306          can be done in one insn.  */
3307       if (l[1] == l[0]
3308           && !(SPARC_SETHI_P (l[0])
3309                || SPARC_SIMM13_P (l[0])))
3310         {
3311           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3312                                 gen_highpart (SImode, operands[0])));
3313         }
3314       else
3315         {
3316           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3317                                 GEN_INT (l[1])));
3318         }
3319     }
3320   DONE;
3321 }")
3322
3323 (define_expand "movdf"
3324   [(set (match_operand:DF 0 "general_operand" "")
3325         (match_operand:DF 1 "general_operand" ""))]
3326   ""
3327   "
3328 {
3329   /* Force DFmode constants into memory.  */
3330   if (GET_CODE (operands[0]) == REG
3331       && CONSTANT_P (operands[1]))
3332     {
3333       if (TARGET_VIS
3334           && GET_CODE (operands[1]) == CONST_DOUBLE
3335           && fp_zero_operand (operands[1]))
3336         goto movdf_is_ok;
3337
3338       /* emit_group_store will send such bogosity to us when it is
3339          not storing directly into memory.  So fix this up to avoid
3340          crashes in output_constant_pool.  */
3341       if (operands [1] == const0_rtx)
3342         operands[1] = CONST0_RTX (DFmode);
3343       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3344                                                    operands[1]));
3345     }
3346
3347   /* Handle MEM cases first.  */
3348   if (GET_CODE (operands[0]) == MEM)
3349     {
3350       if (register_operand (operands[1], DFmode))
3351         goto movdf_is_ok;
3352
3353       if (! reload_in_progress)
3354         {
3355           operands[0] = validize_mem (operands[0]);
3356           operands[1] = force_reg (DFmode, operands[1]);
3357         }
3358     }
3359
3360   /* Fixup PIC cases.  */
3361   if (flag_pic)
3362     {
3363       if (CONSTANT_P (operands[1])
3364           && pic_address_needs_scratch (operands[1]))
3365         operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
3366
3367       if (symbolic_operand (operands[1], DFmode))
3368         {
3369           operands[1] = legitimize_pic_address (operands[1],
3370                                                 DFmode,
3371                                                 (reload_in_progress ?
3372                                                  operands[0] :
3373                                                  NULL_RTX));
3374         }
3375     }
3376
3377  movdf_is_ok:
3378   ;
3379 }")
3380
3381 ;; Be careful, fmovd does not exist when !v9.
3382 (define_insn "*movdf_insn_sp32"
3383   [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,e,r,r,o,e,o")
3384         (match_operand:DF 1 "input_operand"    "T,e,T,U,e,r,o,r,o,e"))]
3385   "TARGET_FPU
3386    && ! TARGET_V9
3387    && (register_operand (operands[0], DFmode)
3388        || register_operand (operands[1], DFmode))"
3389   "@
3390   ldd\\t%1, %0
3391   std\\t%1, %0
3392   ldd\\t%1, %0
3393   std\\t%1, %0
3394   #
3395   #
3396   #
3397   #
3398   #
3399   #"
3400  [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
3401   (set_attr "length" "1,1,1,1,2,2,2,2,2,2")])
3402
3403 (define_insn "*movdf_no_e_insn_sp32"
3404   [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,r,r,o")
3405         (match_operand:DF 1 "input_operand"    "T,U,r,o,r"))]
3406   "! TARGET_FPU
3407    && ! TARGET_ARCH64
3408    && (register_operand (operands[0], DFmode)
3409        || register_operand (operands[1], DFmode))"
3410   "@
3411   ldd\\t%1, %0
3412   std\\t%1, %0
3413   #
3414   #
3415   #"
3416   [(set_attr "type" "load,store,*,*,*")
3417    (set_attr "length" "1,1,2,2,2")])
3418
3419 ;; We have available v9 double floats but not 64-bit
3420 ;; integer registers.
3421 (define_insn "*movdf_insn_v9only"
3422   [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,U,T,r,r,o")
3423         (match_operand:DF 1 "input_operand"    "e,m,e,T,U,r,o,r"))]
3424   "TARGET_FPU
3425    && TARGET_V9
3426    && ! TARGET_ARCH64
3427    && (register_operand (operands[0], DFmode)
3428        || register_operand (operands[1], DFmode))"
3429   "@
3430   fmovd\\t%1, %0
3431   ldd\\t%1, %0
3432   std\\t%1, %0
3433   ldd\\t%1, %0
3434   std\\t%1, %0
3435   #
3436   #
3437   #"
3438   [(set_attr "type" "fpmove,load,store,load,store,*,*,*")
3439    (set_attr "length" "1,1,1,1,1,2,2,2")])
3440
3441 ;; We have available both v9 double floats and 64-bit
3442 ;; integer registers.
3443 (define_insn "*movdf_insn_sp64"
3444   [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,r,r,m")
3445         (match_operand:DF 1 "input_operand"    "e,m,e,r,m,r"))]
3446   "TARGET_FPU
3447    && TARGET_V9
3448    && TARGET_ARCH64
3449    && (register_operand (operands[0], DFmode)
3450        || register_operand (operands[1], DFmode))"
3451   "@
3452   fmovd\\t%1, %0
3453   ldd\\t%1, %0
3454   std\\t%1, %0
3455   mov\\t%1, %0
3456   ldx\\t%1, %0
3457   stx\\t%1, %0"
3458   [(set_attr "type" "fpmove,load,store,move,load,store")
3459    (set_attr "length" "1")])
3460
3461 (define_insn "*movdf_no_e_insn_sp64"
3462   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
3463         (match_operand:DF 1 "input_operand"    "r,m,r"))]
3464   "! TARGET_FPU
3465    && TARGET_ARCH64
3466    && (register_operand (operands[0], DFmode)
3467        || register_operand (operands[1], DFmode))"
3468   "@
3469   mov\\t%1, %0
3470   ldx\\t%1, %0
3471   stx\\t%1, %0"
3472   [(set_attr "type" "move,load,store")
3473    (set_attr "length" "1")])
3474
3475 ;; Ok, now the splits to handle all the multi insn and
3476 ;; mis-aligned memory address cases.
3477 ;; In these splits please take note that we must be
3478 ;; careful when V9 but not ARCH64 because the integer
3479 ;; register DFmode cases must be handled.
3480 (define_split
3481   [(set (match_operand:DF 0 "register_operand" "")
3482         (match_operand:DF 1 "register_operand" ""))]
3483   "(! TARGET_V9
3484     || (! TARGET_ARCH64
3485         && ((GET_CODE (operands[0]) == REG
3486              && REGNO (operands[0]) < 32)
3487             || (GET_CODE (operands[0]) == SUBREG
3488                 && GET_CODE (SUBREG_REG (operands[0])) == REG
3489                 && REGNO (SUBREG_REG (operands[0])) < 32))))
3490    && reload_completed"
3491   [(clobber (const_int 0))]
3492   "
3493 {
3494   rtx set_dest = operands[0];
3495   rtx set_src = operands[1];
3496   rtx dest1, dest2;
3497   rtx src1, src2;
3498
3499   if (GET_CODE (set_dest) == SUBREG)
3500     set_dest = alter_subreg (set_dest);
3501   if (GET_CODE (set_src) == SUBREG)
3502     set_src = alter_subreg (set_src);
3503
3504   dest1 = gen_highpart (SFmode, set_dest);
3505   dest2 = gen_lowpart (SFmode, set_dest);
3506   src1 = gen_highpart (SFmode, set_src);
3507   src2 = gen_lowpart (SFmode, set_src);
3508
3509   /* Now emit using the real source and destination we found, swapping
3510      the order if we detect overlap.  */
3511   if (reg_overlap_mentioned_p (dest1, src2))
3512     {
3513       emit_insn (gen_movsf (dest2, src2));
3514       emit_insn (gen_movsf (dest1, src1));
3515     }
3516   else
3517     {
3518       emit_insn (gen_movsf (dest1, src1));
3519       emit_insn (gen_movsf (dest2, src2));
3520     }
3521   DONE;
3522 }")
3523
3524 (define_split
3525   [(set (match_operand:DF 0 "register_operand" "")
3526         (match_operand:DF 1 "memory_operand" ""))]
3527   "((! TARGET_V9
3528      || (! TARGET_ARCH64
3529          && ((GET_CODE (operands[0]) == REG
3530               && REGNO (operands[0]) < 32)
3531              || (GET_CODE (operands[0]) == SUBREG
3532                  && GET_CODE (SUBREG_REG (operands[0])) == REG
3533                  && REGNO (SUBREG_REG (operands[0])) < 32))))
3534     && (reload_completed
3535         && (((REGNO (operands[0])) % 2) != 0
3536              || ! mem_min_alignment (operands[1], 8))
3537         && offsettable_memref_p (operands[1])))"
3538   [(clobber (const_int 0))]
3539   "
3540 {
3541   rtx word0 = change_address (operands[1], SFmode, NULL_RTX);
3542   rtx word1 = change_address (operands[1], SFmode,
3543                               plus_constant_for_output (XEXP (word0, 0), 4));
3544
3545   if (GET_CODE (operands[0]) == SUBREG)
3546     operands[0] = alter_subreg (operands[0]);
3547
3548   if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
3549     {
3550       emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3551                             word1));
3552       emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3553                             word0));
3554     }
3555   else
3556     {
3557       emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3558                             word0));
3559       emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3560                             word1));
3561     }
3562   DONE;
3563 }")
3564
3565 (define_split
3566   [(set (match_operand:DF 0 "memory_operand" "")
3567         (match_operand:DF 1 "register_operand" ""))]
3568   "((! TARGET_V9
3569      || (! TARGET_ARCH64
3570          && ((GET_CODE (operands[1]) == REG
3571               && REGNO (operands[1]) < 32)
3572              || (GET_CODE (operands[1]) == SUBREG
3573                  && GET_CODE (SUBREG_REG (operands[1])) == REG
3574                  && REGNO (SUBREG_REG (operands[1])) < 32))))
3575     && (reload_completed
3576         && (((REGNO (operands[1])) % 2) != 0
3577              || ! mem_min_alignment (operands[0], 8))
3578         && offsettable_memref_p (operands[0])))"
3579   [(clobber (const_int 0))]
3580   "
3581 {
3582   rtx word0 = change_address (operands[0], SFmode, NULL_RTX);
3583   rtx word1 = change_address (operands[0], SFmode,
3584                               plus_constant_for_output (XEXP (word0, 0), 4));
3585
3586   if (GET_CODE (operands[1]) == SUBREG)
3587     operands[1] = alter_subreg (operands[1]);
3588   emit_insn (gen_movsf (word0,
3589                         gen_highpart (SFmode, operands[1])));
3590   emit_insn (gen_movsf (word1,
3591                         gen_lowpart (SFmode, operands[1])));
3592   DONE;
3593 }")
3594
3595 (define_insn "*clear_tf"
3596   [(set (match_operand:TF 0 "register_operand" "=e")
3597         (match_operand:TF 1 "const_double_operand" ""))]
3598   "TARGET_VIS
3599    && fp_zero_operand (operands[1])"
3600   "#"
3601   [(set_attr "type" "fpmove")
3602    (set_attr "length" "2")])
3603
3604 (define_split
3605   [(set (match_operand:TF 0 "register_operand" "")
3606         (match_operand:TF 1 "const_double_operand" ""))]
3607   "TARGET_VIS && reload_completed
3608    && fp_zero_operand (operands[1])"
3609   [(set (subreg:DF (match_dup 0) 0) (match_dup 1))
3610    (set (subreg:DF (match_dup 0) 8) (match_dup 1))]
3611   "
3612 {
3613   operands[1] = CONST0_RTX (DFmode);
3614 }
3615 ")
3616
3617 (define_insn "*clear_tfp"
3618   [(set (match_operand:TF 0 "memory_operand" "=m")
3619         (match_operand:TF 1 "const_double_operand" ""))]
3620   "! TARGET_LIVE_G0
3621    && TARGET_V9
3622    && fp_zero_operand (operands[1])"
3623   "#"
3624   [(set_attr "type" "fpmove")
3625    (set_attr "length" "2")])
3626
3627 (define_split
3628   [(set (match_operand:TF 0 "memory_operand" "=m")
3629         (match_operand:TF 1 "const_double_operand" ""))]
3630   "! TARGET_LIVE_G0
3631    && TARGET_V9 && reload_completed
3632    && fp_zero_operand (operands[1])"
3633   [(set (subreg:DF (match_dup 0) 0) (match_dup 1))
3634    (set (subreg:DF (match_dup 0) 8) (match_dup 1))]
3635   "
3636 {
3637   operands[1] = CONST0_RTX (DFmode);
3638 }
3639 ")
3640
3641 (define_expand "movtf"
3642   [(set (match_operand:TF 0 "general_operand" "")
3643         (match_operand:TF 1 "general_operand" ""))]
3644   ""
3645   "
3646 {
3647   /* Force TFmode constants into memory. */
3648   if (GET_CODE (operands[0]) == REG
3649       && CONSTANT_P (operands[1]))
3650     {
3651       if (TARGET_VIS
3652           && GET_CODE (operands[1]) == CONST_DOUBLE
3653           && fp_zero_operand (operands[1]))
3654         goto movtf_is_ok;
3655
3656       /* emit_group_store will send such bogosity to us when it is
3657          not storing directly into memory.  So fix this up to avoid
3658          crashes in output_constant_pool.  */
3659       if (operands [1] == const0_rtx)
3660         operands[1] = CONST0_RTX (TFmode);
3661       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3662                                                    operands[1]));
3663     }
3664
3665   /* Handle MEM cases first, note that only v9 guarentees
3666      full 16-byte alignment for quads. */
3667   if (GET_CODE (operands[0]) == MEM)
3668     {
3669       if (register_operand (operands[1], TFmode))
3670         goto movtf_is_ok;
3671
3672       if (! reload_in_progress)
3673         {
3674           operands[0] = validize_mem (operands[0]);
3675           operands[1] = force_reg (TFmode, operands[1]);
3676         }
3677     }
3678
3679   /* Fixup PIC cases.  */
3680   if (flag_pic)
3681     {
3682       if (CONSTANT_P (operands[1])
3683           && pic_address_needs_scratch (operands[1]))
3684         operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
3685
3686       if (symbolic_operand (operands[1], TFmode))
3687         {
3688           operands[1] = legitimize_pic_address (operands[1],
3689                                                 TFmode,
3690                                                 (reload_in_progress ?
3691                                                  operands[0] :
3692                                                  NULL_RTX));
3693         }
3694     }
3695
3696  movtf_is_ok:
3697   ;
3698 }")
3699
3700 ;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
3701 ;; we must split them all.  :-(
3702 (define_insn "*movtf_insn_sp32"
3703   [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,o,e,r,r,o")
3704         (match_operand:TF 1 "input_operand"    "o,e,o,U,e,r,o,r"))]
3705   "TARGET_FPU
3706    && ! TARGET_ARCH64
3707    && (register_operand (operands[0], TFmode)
3708        || register_operand (operands[1], TFmode))"
3709   "#"
3710   [(set_attr "length" "4")])
3711
3712 ;; Exactly the same as above, except that all `e' cases are deleted.
3713 ;; This is necessary to prevent reload from ever trying to use a `e' reg
3714 ;; when -mno-fpu.
3715
3716 (define_insn "*movtf_no_e_insn_sp32"
3717   [(set (match_operand:TF 0 "nonimmediate_operand" "=U,o,r,r,o")
3718         (match_operand:TF 1 "input_operand"    "o,U,r,o,r"))]
3719   "! TARGET_FPU
3720    && ! TARGET_ARCH64
3721    && (register_operand (operands[0], TFmode)
3722        || register_operand (operands[1], TFmode))"
3723   "#"
3724   [(set_attr "length" "4")])
3725
3726 ;; Now handle the float reg cases directly when arch64,
3727 ;; hard_quad, and proper reg number alignment are all true.
3728 (define_insn "*movtf_insn_hq_sp64"
3729   [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,r,r,o")
3730         (match_operand:TF 1 "input_operand"    "e,m,e,r,o,r"))]
3731   "TARGET_FPU
3732    && TARGET_ARCH64
3733    && TARGET_V9
3734    && TARGET_HARD_QUAD
3735    && (register_operand (operands[0], TFmode)
3736        || register_operand (operands[1], TFmode))"
3737   "@
3738   fmovq\\t%1, %0
3739   ldq\\t%1, %0
3740   stq\\t%1, %0
3741   #
3742   #
3743   #"
3744   [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
3745    (set_attr "length" "1,1,1,2,2,2")])
3746
3747 ;; Now we allow the integer register cases even when
3748 ;; only arch64 is true.
3749 (define_insn "*movtf_insn_sp64"
3750   [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r,o,e,r")
3751         (match_operand:TF 1 "input_operand"    "o,e,o,r,e,r"))]
3752   "TARGET_FPU
3753    && TARGET_ARCH64
3754    && ! TARGET_HARD_QUAD
3755    && (register_operand (operands[0], TFmode)
3756        || register_operand (operands[1], TFmode))"
3757   "#"
3758   [(set_attr "length" "2")])
3759
3760 (define_insn "*movtf_no_e_insn_sp64"
3761   [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,r")
3762         (match_operand:TF 1 "input_operand"    "o,r,r"))]
3763   "! TARGET_FPU
3764    && TARGET_ARCH64
3765    && (register_operand (operands[0], TFmode)
3766        || register_operand (operands[1], TFmode))"
3767   "#"
3768   [(set_attr "length" "2")])
3769
3770 ;; Now all the splits to handle multi-insn TF mode moves.
3771 (define_split
3772   [(set (match_operand:TF 0 "register_operand" "")
3773         (match_operand:TF 1 "register_operand" ""))]
3774   "reload_completed
3775    && (! TARGET_ARCH64
3776        || (TARGET_FPU
3777            && ! TARGET_HARD_QUAD))"
3778   [(clobber (const_int 0))]
3779   "
3780 {
3781   rtx set_dest = operands[0];
3782   rtx set_src = operands[1];
3783   rtx dest1, dest2;
3784   rtx src1, src2;
3785
3786   if (GET_CODE (set_dest) == SUBREG)
3787     set_dest = alter_subreg (set_dest);
3788   if (GET_CODE (set_src) == SUBREG)
3789     set_src = alter_subreg (set_src);
3790
3791   dest1 = gen_df_reg (set_dest, 0);
3792   dest2 = gen_df_reg (set_dest, 1);
3793   src1 = gen_df_reg (set_src, 0);
3794   src2 = gen_df_reg (set_src, 1);
3795
3796   /* Now emit using the real source and destination we found, swapping
3797      the order if we detect overlap.  */
3798   if (reg_overlap_mentioned_p (dest1, src2))
3799     {
3800       emit_insn (gen_movdf (dest2, src2));
3801       emit_insn (gen_movdf (dest1, src1));
3802     }
3803   else
3804     {
3805       emit_insn (gen_movdf (dest1, src1));
3806       emit_insn (gen_movdf (dest2, src2));
3807     }
3808   DONE;
3809 }")
3810
3811 (define_split
3812   [(set (match_operand:TF 0 "register_operand" "")
3813         (match_operand:TF 1 "memory_operand" ""))]
3814   "(reload_completed
3815     && offsettable_memref_p (operands[1]))"
3816   [(clobber (const_int 0))]
3817   "
3818 {
3819   rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
3820   rtx word1 = change_address (operands[1], DFmode,
3821                               plus_constant_for_output (XEXP (word0, 0), 8));
3822   rtx set_dest, dest1, dest2;
3823
3824   set_dest = operands[0];
3825   if (GET_CODE (set_dest) == SUBREG)
3826     set_dest = alter_subreg (set_dest);
3827
3828   dest1 = gen_df_reg (set_dest, 0);
3829   dest2 = gen_df_reg (set_dest, 1);
3830
3831   /* Now output, ordering such that we don't clobber any registers
3832      mentioned in the address.  */
3833   if (reg_overlap_mentioned_p (dest1, word1))
3834
3835     {
3836       emit_insn (gen_movdf (dest2, word1));
3837       emit_insn (gen_movdf (dest1, word0));
3838     }
3839   else
3840    {
3841       emit_insn (gen_movdf (dest1, word0));
3842       emit_insn (gen_movdf (dest2, word1));
3843    }
3844   DONE;
3845 }")
3846
3847 (define_split
3848   [(set (match_operand:TF 0 "memory_operand" "")
3849         (match_operand:TF 1 "register_operand" ""))]
3850   "(reload_completed
3851     && offsettable_memref_p (operands[0]))"
3852   [(clobber (const_int 0))]
3853   "
3854 {
3855   rtx word1 = change_address (operands[0], DFmode, NULL_RTX);
3856   rtx word2 = change_address (operands[0], DFmode,
3857                               plus_constant_for_output (XEXP (word1, 0), 8));
3858   rtx set_src;
3859
3860   set_src = operands[1];
3861   if (GET_CODE (set_src) == SUBREG)
3862     set_src = alter_subreg (set_src);
3863
3864   emit_insn (gen_movdf (word1, gen_df_reg (set_src, 0)));
3865   emit_insn (gen_movdf (word2, gen_df_reg (set_src, 1)));
3866   DONE;
3867 }")
3868 \f
3869 ;; Sparc V9 conditional move instructions.
3870
3871 ;; We can handle larger constants here for some flavors, but for now we keep
3872 ;; it simple and only allow those constants supported by all flavours.
3873 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3874 ;; 3 contains the constant if one is present, but we handle either for
3875 ;; generality (sparc.c puts a constant in operand 2).
3876
3877 (define_expand "movqicc"
3878   [(set (match_operand:QI 0 "register_operand" "")
3879         (if_then_else:QI (match_operand 1 "comparison_operator" "")
3880                          (match_operand:QI 2 "arith10_operand" "")
3881                          (match_operand:QI 3 "arith10_operand" "")))]
3882   "TARGET_V9"
3883   "
3884 {
3885   enum rtx_code code = GET_CODE (operands[1]);
3886
3887   if (GET_MODE (sparc_compare_op0) == DImode
3888       && ! TARGET_ARCH64)
3889     FAIL;
3890
3891   if (sparc_compare_op1 == const0_rtx
3892       && GET_CODE (sparc_compare_op0) == REG
3893       && GET_MODE (sparc_compare_op0) == DImode
3894       && v9_regcmp_p (code))
3895     {
3896       operands[1] = gen_rtx_fmt_ee (code, DImode,
3897                              sparc_compare_op0, sparc_compare_op1);
3898     }
3899   else
3900     {
3901       rtx cc_reg = gen_compare_reg (code,
3902                                     sparc_compare_op0, sparc_compare_op1);
3903       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3904     }
3905 }")
3906
3907 (define_expand "movhicc"
3908   [(set (match_operand:HI 0 "register_operand" "")
3909         (if_then_else:HI (match_operand 1 "comparison_operator" "")
3910                          (match_operand:HI 2 "arith10_operand" "")
3911                          (match_operand:HI 3 "arith10_operand" "")))]
3912   "TARGET_V9"
3913   "
3914 {
3915   enum rtx_code code = GET_CODE (operands[1]);
3916
3917   if (GET_MODE (sparc_compare_op0) == DImode
3918       && ! TARGET_ARCH64)
3919     FAIL;
3920
3921   if (sparc_compare_op1 == const0_rtx
3922       && GET_CODE (sparc_compare_op0) == REG
3923       && GET_MODE (sparc_compare_op0) == DImode
3924       && v9_regcmp_p (code))
3925     {
3926       operands[1] = gen_rtx_fmt_ee (code, DImode,
3927                              sparc_compare_op0, sparc_compare_op1);
3928     }
3929   else
3930     {
3931       rtx cc_reg = gen_compare_reg (code,
3932                                     sparc_compare_op0, sparc_compare_op1);
3933       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3934     }
3935 }")
3936
3937 (define_expand "movsicc"
3938   [(set (match_operand:SI 0 "register_operand" "")
3939         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3940                          (match_operand:SI 2 "arith10_operand" "")
3941                          (match_operand:SI 3 "arith10_operand" "")))]
3942   "TARGET_V9"
3943   "
3944 {
3945   enum rtx_code code = GET_CODE (operands[1]);
3946   enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3947
3948   if (sparc_compare_op1 == const0_rtx
3949       && GET_CODE (sparc_compare_op0) == REG
3950       && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3951     {
3952       operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3953                              sparc_compare_op0, sparc_compare_op1);
3954     }
3955   else
3956     {
3957       rtx cc_reg = gen_compare_reg (code,
3958                                     sparc_compare_op0, sparc_compare_op1);
3959       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3960                                     cc_reg, const0_rtx);
3961     }
3962 }")
3963
3964 (define_expand "movdicc"
3965   [(set (match_operand:DI 0 "register_operand" "")
3966         (if_then_else:DI (match_operand 1 "comparison_operator" "")
3967                          (match_operand:DI 2 "arith10_double_operand" "")
3968                          (match_operand:DI 3 "arith10_double_operand" "")))]
3969   "TARGET_ARCH64"
3970   "
3971 {
3972   enum rtx_code code = GET_CODE (operands[1]);
3973
3974   if (sparc_compare_op1 == const0_rtx
3975       && GET_CODE (sparc_compare_op0) == REG
3976       && GET_MODE (sparc_compare_op0) == DImode
3977       && v9_regcmp_p (code))
3978     {
3979       operands[1] = gen_rtx_fmt_ee (code, DImode,
3980                              sparc_compare_op0, sparc_compare_op1);
3981     }
3982   else
3983     {
3984       rtx cc_reg = gen_compare_reg (code,
3985                                     sparc_compare_op0, sparc_compare_op1);
3986       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3987                                     cc_reg, const0_rtx);
3988     }
3989 }")
3990
3991 (define_expand "movsfcc"
3992   [(set (match_operand:SF 0 "register_operand" "")
3993         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3994                          (match_operand:SF 2 "register_operand" "")
3995                          (match_operand:SF 3 "register_operand" "")))]
3996   "TARGET_V9 && TARGET_FPU"
3997   "
3998 {
3999   enum rtx_code code = GET_CODE (operands[1]);
4000
4001   if (GET_MODE (sparc_compare_op0) == DImode
4002       && ! TARGET_ARCH64)
4003     FAIL;
4004
4005   if (sparc_compare_op1 == const0_rtx
4006       && GET_CODE (sparc_compare_op0) == REG
4007       && GET_MODE (sparc_compare_op0) == DImode
4008       && v9_regcmp_p (code))
4009     {
4010       operands[1] = gen_rtx_fmt_ee (code, DImode,
4011                              sparc_compare_op0, sparc_compare_op1);
4012     }
4013   else
4014     {
4015       rtx cc_reg = gen_compare_reg (code,
4016                                     sparc_compare_op0, sparc_compare_op1);
4017       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
4018     }
4019 }")
4020
4021 (define_expand "movdfcc"
4022   [(set (match_operand:DF 0 "register_operand" "")
4023         (if_then_else:DF (match_operand 1 "comparison_operator" "")
4024                          (match_operand:DF 2 "register_operand" "")
4025                          (match_operand:DF 3 "register_operand" "")))]
4026   "TARGET_V9 && TARGET_FPU"
4027   "
4028 {
4029   enum rtx_code code = GET_CODE (operands[1]);
4030
4031   if (GET_MODE (sparc_compare_op0) == DImode
4032       && ! TARGET_ARCH64)
4033     FAIL;
4034
4035   if (sparc_compare_op1 == const0_rtx
4036       && GET_CODE (sparc_compare_op0) == REG
4037       && GET_MODE (sparc_compare_op0) == DImode
4038       && v9_regcmp_p (code))
4039     {
4040       operands[1] = gen_rtx_fmt_ee (code, DImode,
4041                              sparc_compare_op0, sparc_compare_op1);
4042     }
4043   else
4044     {
4045       rtx cc_reg = gen_compare_reg (code,
4046                                     sparc_compare_op0, sparc_compare_op1);
4047       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
4048     }
4049 }")
4050
4051 (define_expand "movtfcc"
4052   [(set (match_operand:TF 0 "register_operand" "")
4053         (if_then_else:TF (match_operand 1 "comparison_operator" "")
4054                          (match_operand:TF 2 "register_operand" "")
4055                          (match_operand:TF 3 "register_operand" "")))]
4056   "TARGET_V9 && TARGET_FPU"
4057   "
4058 {
4059   enum rtx_code code = GET_CODE (operands[1]);
4060
4061   if (GET_MODE (sparc_compare_op0) == DImode
4062       && ! TARGET_ARCH64)
4063     FAIL;
4064
4065   if (sparc_compare_op1 == const0_rtx
4066       && GET_CODE (sparc_compare_op0) == REG
4067       && GET_MODE (sparc_compare_op0) == DImode
4068       && v9_regcmp_p (code))
4069     {
4070       operands[1] = gen_rtx_fmt_ee (code, DImode,
4071                              sparc_compare_op0, sparc_compare_op1);
4072     }
4073   else
4074     {
4075       rtx cc_reg = gen_compare_reg (code,
4076                                     sparc_compare_op0, sparc_compare_op1);
4077       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
4078     }
4079 }")
4080
4081 ;; Conditional move define_insns.
4082
4083 (define_insn "*movqi_cc_sp64"
4084   [(set (match_operand:QI 0 "register_operand" "=r,r")
4085         (if_then_else:QI (match_operator 1 "comparison_operator"
4086                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4087                                  (const_int 0)])
4088                          (match_operand:QI 3 "arith11_operand" "rL,0")
4089                          (match_operand:QI 4 "arith11_operand" "0,rL")))]
4090   "TARGET_V9"
4091   "@
4092    mov%C1\\t%x2, %3, %0
4093    mov%c1\\t%x2, %4, %0"
4094   [(set_attr "type" "cmove")
4095    (set_attr "length" "1")])
4096
4097 (define_insn "*movhi_cc_sp64"
4098   [(set (match_operand:HI 0 "register_operand" "=r,r")
4099         (if_then_else:HI (match_operator 1 "comparison_operator"
4100                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4101                                  (const_int 0)])
4102                          (match_operand:HI 3 "arith11_operand" "rL,0")
4103                          (match_operand:HI 4 "arith11_operand" "0,rL")))]
4104   "TARGET_V9"
4105   "@
4106    mov%C1\\t%x2, %3, %0
4107    mov%c1\\t%x2, %4, %0"
4108   [(set_attr "type" "cmove")
4109    (set_attr "length" "1")])
4110
4111 (define_insn "*movsi_cc_sp64"
4112   [(set (match_operand:SI 0 "register_operand" "=r,r")
4113         (if_then_else:SI (match_operator 1 "comparison_operator"
4114                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4115                                  (const_int 0)])
4116                          (match_operand:SI 3 "arith11_operand" "rL,0")
4117                          (match_operand:SI 4 "arith11_operand" "0,rL")))]
4118   "TARGET_V9"
4119   "@
4120    mov%C1\\t%x2, %3, %0
4121    mov%c1\\t%x2, %4, %0"
4122   [(set_attr "type" "cmove")
4123    (set_attr "length" "1")])
4124
4125 ;; ??? The constraints of operands 3,4 need work.
4126 (define_insn "*movdi_cc_sp64"
4127   [(set (match_operand:DI 0 "register_operand" "=r,r")
4128         (if_then_else:DI (match_operator 1 "comparison_operator"
4129                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4130                                  (const_int 0)])
4131                          (match_operand:DI 3 "arith11_double_operand" "rLH,0")
4132                          (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
4133   "TARGET_ARCH64"
4134   "@
4135    mov%C1\\t%x2, %3, %0
4136    mov%c1\\t%x2, %4, %0"
4137   [(set_attr "type" "cmove")
4138    (set_attr "length" "1")])
4139
4140 (define_insn "*movdi_cc_sp64_trunc"
4141   [(set (match_operand:SI 0 "register_operand" "=r,r")
4142         (if_then_else:SI (match_operator 1 "comparison_operator"
4143                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4144                                  (const_int 0)])
4145                          (match_operand:SI 3 "arith11_double_operand" "rLH,0")
4146                          (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
4147   "TARGET_ARCH64"
4148   "@
4149    mov%C1\\t%x2, %3, %0
4150    mov%c1\\t%x2, %4, %0"
4151   [(set_attr "type" "cmove")
4152    (set_attr "length" "1")])
4153
4154 (define_insn "*movsf_cc_sp64"
4155   [(set (match_operand:SF 0 "register_operand" "=f,f")
4156         (if_then_else:SF (match_operator 1 "comparison_operator"
4157                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4158                                  (const_int 0)])
4159                          (match_operand:SF 3 "register_operand" "f,0")
4160                          (match_operand:SF 4 "register_operand" "0,f")))]
4161   "TARGET_V9 && TARGET_FPU"
4162   "@
4163    fmovs%C1\\t%x2, %3, %0
4164    fmovs%c1\\t%x2, %4, %0"
4165   [(set_attr "type" "fpcmove")
4166    (set_attr "length" "1")])
4167
4168 (define_insn "movdf_cc_sp64"
4169   [(set (match_operand:DF 0 "register_operand" "=e,e")
4170         (if_then_else:DF (match_operator 1 "comparison_operator"
4171                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4172                                  (const_int 0)])
4173                          (match_operand:DF 3 "register_operand" "e,0")
4174                          (match_operand:DF 4 "register_operand" "0,e")))]
4175   "TARGET_V9 && TARGET_FPU"
4176   "@
4177    fmovd%C1\\t%x2, %3, %0
4178    fmovd%c1\\t%x2, %4, %0"
4179   [(set_attr "type" "fpcmove")
4180    (set_attr "length" "1")])
4181
4182 (define_insn "*movtf_cc_hq_sp64"
4183   [(set (match_operand:TF 0 "register_operand" "=e,e")
4184         (if_then_else:TF (match_operator 1 "comparison_operator"
4185                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4186                                  (const_int 0)])
4187                          (match_operand:TF 3 "register_operand" "e,0")
4188                          (match_operand:TF 4 "register_operand" "0,e")))]
4189   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4190   "@
4191    fmovq%C1\\t%x2, %3, %0
4192    fmovq%c1\\t%x2, %4, %0"
4193   [(set_attr "type" "fpcmove")
4194    (set_attr "length" "1")])
4195
4196 (define_insn "*movtf_cc_sp64"
4197   [(set (match_operand:TF 0 "register_operand" "=e,e")
4198         (if_then_else:TF (match_operator 1 "comparison_operator"
4199                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4200                                  (const_int 0)])
4201                          (match_operand:TF 3 "register_operand" "e,0")
4202                          (match_operand:TF 4 "register_operand" "0,e")))]
4203   "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
4204   "#"
4205   [(set_attr "type" "fpcmove")
4206    (set_attr "length" "2")])
4207
4208 (define_split
4209   [(set (match_operand:TF 0 "register_operand" "=e,e")
4210         (if_then_else:TF (match_operator 1 "comparison_operator"
4211                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
4212                                  (const_int 0)])
4213                          (match_operand:TF 3 "register_operand" "e,0")
4214                          (match_operand:TF 4 "register_operand" "0,e")))]
4215   "reload_completed && TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
4216   [(clobber (const_int 0))]
4217   "
4218 {
4219   rtx set_dest = operands[0];
4220   rtx set_srca = operands[3];
4221   rtx set_srcb = operands[4];
4222   int third = rtx_equal_p (set_dest, set_srca);
4223   rtx dest1, dest2;
4224   rtx srca1, srca2, srcb1, srcb2;
4225
4226   if (GET_CODE (set_dest) == SUBREG)
4227     set_dest = alter_subreg (set_dest);
4228   if (GET_CODE (set_srca) == SUBREG)
4229     set_srca = alter_subreg (set_srca);
4230   if (GET_CODE (set_srcb) == SUBREG)
4231     set_srcb = alter_subreg (set_srcb);
4232
4233   dest1 = gen_df_reg (set_dest, 0);
4234   dest2 = gen_df_reg (set_dest, 1);
4235   srca1 = gen_df_reg (set_srca, 0);
4236   srca2 = gen_df_reg (set_srca, 1);
4237   srcb1 = gen_df_reg (set_srcb, 0);
4238   srcb2 = gen_df_reg (set_srcb, 1);
4239
4240   /* Now emit using the real source and destination we found, swapping
4241      the order if we detect overlap.  */
4242   if ((third && reg_overlap_mentioned_p (dest1, srcb2))
4243       || (!third && reg_overlap_mentioned_p (dest1, srca2)))
4244     {
4245       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
4246       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
4247     }
4248   else
4249     {
4250       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
4251       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
4252     }
4253   DONE;
4254 }")
4255
4256 (define_insn "*movqi_cc_reg_sp64"
4257   [(set (match_operand:QI 0 "register_operand" "=r,r")
4258         (if_then_else:QI (match_operator 1 "v9_regcmp_op"
4259                                 [(match_operand:DI 2 "register_operand" "r,r")
4260                                  (const_int 0)])
4261                          (match_operand:QI 3 "arith10_operand" "rM,0")
4262                          (match_operand:QI 4 "arith10_operand" "0,rM")))]
4263   "TARGET_ARCH64"
4264   "@
4265    movr%D1\\t%2, %r3, %0
4266    movr%d1\\t%2, %r4, %0"
4267   [(set_attr "type" "cmove")
4268    (set_attr "length" "1")])
4269
4270 (define_insn "*movhi_cc_reg_sp64"
4271   [(set (match_operand:HI 0 "register_operand" "=r,r")
4272         (if_then_else:HI (match_operator 1 "v9_regcmp_op"
4273                                 [(match_operand:DI 2 "register_operand" "r,r")
4274                                  (const_int 0)])
4275                          (match_operand:HI 3 "arith10_operand" "rM,0")
4276                          (match_operand:HI 4 "arith10_operand" "0,rM")))]
4277   "TARGET_ARCH64"
4278   "@
4279    movr%D1\\t%2, %r3, %0
4280    movr%d1\\t%2, %r4, %0"
4281   [(set_attr "type" "cmove")
4282    (set_attr "length" "1")])
4283
4284 (define_insn "*movsi_cc_reg_sp64"
4285   [(set (match_operand:SI 0 "register_operand" "=r,r")
4286         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
4287                                 [(match_operand:DI 2 "register_operand" "r,r")
4288                                  (const_int 0)])
4289                          (match_operand:SI 3 "arith10_operand" "rM,0")
4290                          (match_operand:SI 4 "arith10_operand" "0,rM")))]
4291   "TARGET_ARCH64"
4292   "@
4293    movr%D1\\t%2, %r3, %0
4294    movr%d1\\t%2, %r4, %0"
4295   [(set_attr "type" "cmove")
4296    (set_attr "length" "1")])
4297
4298 ;; ??? The constraints of operands 3,4 need work.
4299 (define_insn "*movdi_cc_reg_sp64"
4300   [(set (match_operand:DI 0 "register_operand" "=r,r")
4301         (if_then_else:DI (match_operator 1 "v9_regcmp_op"
4302                                 [(match_operand:DI 2 "register_operand" "r,r")
4303                                  (const_int 0)])
4304                          (match_operand:DI 3 "arith10_double_operand" "rMH,0")
4305                          (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
4306   "TARGET_ARCH64"
4307   "@
4308    movr%D1\\t%2, %r3, %0
4309    movr%d1\\t%2, %r4, %0"
4310   [(set_attr "type" "cmove")
4311    (set_attr "length" "1")])
4312
4313 (define_insn "*movdi_cc_reg_sp64_trunc"
4314   [(set (match_operand:SI 0 "register_operand" "=r,r")
4315         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
4316                                 [(match_operand:DI 2 "register_operand" "r,r")
4317                                  (const_int 0)])
4318                          (match_operand:SI 3 "arith10_double_operand" "rMH,0")
4319                          (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
4320   "TARGET_ARCH64"
4321   "@
4322    movr%D1\\t%2, %r3, %0
4323    movr%d1\\t%2, %r4, %0"
4324   [(set_attr "type" "cmove")
4325    (set_attr "length" "1")])
4326
4327 (define_insn "*movsf_cc_reg_sp64"
4328   [(set (match_operand:SF 0 "register_operand" "=f,f")
4329         (if_then_else:SF (match_operator 1 "v9_regcmp_op"
4330                                 [(match_operand:DI 2 "register_operand" "r,r")
4331                                  (const_int 0)])
4332                          (match_operand:SF 3 "register_operand" "f,0")
4333                          (match_operand:SF 4 "register_operand" "0,f")))]
4334   "TARGET_ARCH64 && TARGET_FPU"
4335   "@
4336    fmovrs%D1\\t%2, %3, %0
4337    fmovrs%d1\\t%2, %4, %0"
4338   [(set_attr "type" "fpcmove")
4339    (set_attr "length" "1")])
4340
4341 (define_insn "movdf_cc_reg_sp64"
4342   [(set (match_operand:DF 0 "register_operand" "=e,e")
4343         (if_then_else:DF (match_operator 1 "v9_regcmp_op"
4344                                 [(match_operand:DI 2 "register_operand" "r,r")
4345                                  (const_int 0)])
4346                          (match_operand:DF 3 "register_operand" "e,0")
4347                          (match_operand:DF 4 "register_operand" "0,e")))]
4348   "TARGET_ARCH64 && TARGET_FPU"
4349   "@
4350    fmovrd%D1\\t%2, %3, %0
4351    fmovrd%d1\\t%2, %4, %0"
4352   [(set_attr "type" "fpcmove")
4353    (set_attr "length" "1")])
4354
4355 (define_insn "*movtf_cc_reg_hq_sp64"
4356   [(set (match_operand:TF 0 "register_operand" "=e,e")
4357         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
4358                                 [(match_operand:DI 2 "register_operand" "r,r")
4359                                  (const_int 0)])
4360                          (match_operand:TF 3 "register_operand" "e,0")
4361                          (match_operand:TF 4 "register_operand" "0,e")))]
4362   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
4363   "@
4364    fmovrq%D1\\t%2, %3, %0
4365    fmovrq%d1\\t%2, %4, %0"
4366   [(set_attr "type" "fpcmove")
4367    (set_attr "length" "1")])
4368
4369 (define_insn "*movtf_cc_reg_sp64"
4370   [(set (match_operand:TF 0 "register_operand" "=e,e")
4371         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
4372                                 [(match_operand:DI 2 "register_operand" "r,r")
4373                                  (const_int 0)])
4374                          (match_operand:TF 3 "register_operand" "e,0")
4375                          (match_operand:TF 4 "register_operand" "0,e")))]
4376   "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
4377   "#"
4378   [(set_attr "type" "fpcmove")
4379    (set_attr "length" "2")])
4380
4381 (define_split
4382   [(set (match_operand:TF 0 "register_operand" "=e,e")
4383         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
4384                                 [(match_operand:DI 2 "register_operand" "r,r")
4385                                  (const_int 0)])
4386                          (match_operand:TF 3 "register_operand" "e,0")
4387                          (match_operand:TF 4 "register_operand" "0,e")))]
4388   "reload_completed && TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
4389   [(clobber (const_int 0))]
4390   "
4391 {
4392   rtx set_dest = operands[0];
4393   rtx set_srca = operands[3];
4394   rtx set_srcb = operands[4];
4395   int third = rtx_equal_p (set_dest, set_srca);
4396   rtx dest1, dest2;
4397   rtx srca1, srca2, srcb1, srcb2;
4398
4399   if (GET_CODE (set_dest) == SUBREG)
4400     set_dest = alter_subreg (set_dest);
4401   if (GET_CODE (set_srca) == SUBREG)
4402     set_srca = alter_subreg (set_srca);
4403   if (GET_CODE (set_srcb) == SUBREG)
4404     set_srcb = alter_subreg (set_srcb);
4405
4406   dest1 = gen_df_reg (set_dest, 0);
4407   dest2 = gen_df_reg (set_dest, 1);
4408   srca1 = gen_df_reg (set_srca, 0);
4409   srca2 = gen_df_reg (set_srca, 1);
4410   srcb1 = gen_df_reg (set_srcb, 0);
4411   srcb2 = gen_df_reg (set_srcb, 1);
4412
4413   /* Now emit using the real source and destination we found, swapping
4414      the order if we detect overlap.  */
4415   if ((third && reg_overlap_mentioned_p (dest1, srcb2))
4416       || (!third && reg_overlap_mentioned_p (dest1, srca2)))
4417     {
4418       emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
4419       emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
4420     }
4421   else
4422     {
4423       emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
4424       emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
4425     }
4426   DONE;
4427 }")
4428
4429 \f
4430 ;;- zero extension instructions
4431
4432 ;; These patterns originally accepted general_operands, however, slightly
4433 ;; better code is generated by only accepting register_operands, and then
4434 ;; letting combine generate the ldu[hb] insns.
4435
4436 (define_expand "zero_extendhisi2"
4437   [(set (match_operand:SI 0 "register_operand" "")
4438         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
4439   ""
4440   "
4441 {
4442   rtx temp = gen_reg_rtx (SImode);
4443   rtx shift_16 = GEN_INT (16);
4444   int op1_subword = 0;
4445
4446   if (GET_CODE (operand1) == SUBREG)
4447     {
4448       op1_subword = SUBREG_WORD (operand1);
4449       operand1 = XEXP (operand1, 0);
4450     }
4451
4452   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
4453                           shift_16));
4454   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
4455   DONE;
4456 }")
4457
4458 (define_insn "*zero_extendhisi2_insn"
4459   [(set (match_operand:SI 0 "register_operand" "=r")
4460         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4461   ""
4462   "lduh\\t%1, %0"
4463   [(set_attr "type" "load")
4464    (set_attr "length" "1")])
4465
4466 (define_expand "zero_extendqihi2"
4467   [(set (match_operand:HI 0 "register_operand" "")
4468         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
4469   ""
4470   "")
4471
4472 (define_insn "*zero_extendqihi2_insn"
4473   [(set (match_operand:HI 0 "register_operand" "=r,r")
4474         (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
4475   "GET_CODE (operands[1]) != CONST_INT"
4476   "@
4477    and\\t%1, 0xff, %0
4478    ldub\\t%1, %0"
4479   [(set_attr "type" "unary,load")
4480    (set_attr "length" "1")])
4481
4482 (define_expand "zero_extendqisi2"
4483   [(set (match_operand:SI 0 "register_operand" "")
4484         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4485   ""
4486   "")
4487
4488 (define_insn "*zero_extendqisi2_insn"
4489   [(set (match_operand:SI 0 "register_operand" "=r,r")
4490         (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
4491   "GET_CODE (operands[1]) != CONST_INT"
4492   "@
4493    and\\t%1, 0xff, %0
4494    ldub\\t%1, %0"
4495   [(set_attr "type" "unary,load")
4496    (set_attr "length" "1")])
4497
4498 (define_expand "zero_extendqidi2"
4499   [(set (match_operand:DI 0 "register_operand" "")
4500         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
4501   "TARGET_ARCH64"
4502   "")
4503
4504 (define_insn "*zero_extendqidi2_insn"
4505   [(set (match_operand:DI 0 "register_operand" "=r,r")
4506         (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
4507   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4508   "@
4509    and\\t%1, 0xff, %0
4510    ldub\\t%1, %0"
4511   [(set_attr "type" "unary,load")
4512    (set_attr "length" "1")])
4513
4514 (define_expand "zero_extendhidi2"
4515   [(set (match_operand:DI 0 "register_operand" "")
4516         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
4517   "TARGET_ARCH64"
4518   "
4519 {
4520   rtx temp = gen_reg_rtx (DImode);
4521   rtx shift_48 = GEN_INT (48);
4522   int op1_subword = 0;
4523
4524   if (GET_CODE (operand1) == SUBREG)
4525     {
4526       op1_subword = SUBREG_WORD (operand1);
4527       operand1 = XEXP (operand1, 0);
4528     }
4529
4530   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
4531                           shift_48));
4532   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
4533   DONE;
4534 }")
4535
4536 (define_insn "*zero_extendhidi2_insn"
4537   [(set (match_operand:DI 0 "register_operand" "=r")
4538         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4539   "TARGET_ARCH64"
4540   "lduh\\t%1, %0"
4541   [(set_attr "type" "load")
4542    (set_attr "length" "1")])
4543
4544
4545 ;; ??? Write truncdisi pattern using sra?
4546
4547 (define_expand "zero_extendsidi2"
4548   [(set (match_operand:DI 0 "register_operand" "")
4549         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
4550   ""
4551   "")
4552
4553 (define_insn "*zero_extendsidi2_insn_sp64"
4554   [(set (match_operand:DI 0 "register_operand" "=r,r")
4555         (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4556   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4557   "@
4558    srl\\t%1, 0, %0
4559    lduw\\t%1, %0"
4560   [(set_attr "type" "shift,load")
4561    (set_attr "length" "1")])
4562
4563 (define_insn "*zero_extendsidi2_insn_sp32"
4564   [(set (match_operand:DI 0 "register_operand" "=r")
4565         (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4566   "! TARGET_ARCH64"
4567   "#"
4568   [(set_attr "type" "unary")
4569    (set_attr "length" "2")])
4570
4571 (define_split
4572   [(set (match_operand:DI 0 "register_operand" "")
4573         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
4574   "! TARGET_ARCH64 && reload_completed"
4575   [(set (match_dup 2) (match_dup 3))
4576    (set (match_dup 4) (match_dup 5))]
4577   "
4578 {
4579   rtx dest1, dest2;
4580
4581   if (GET_CODE (operands[0]) == SUBREG)
4582     operands[0] = alter_subreg (operands[0]);
4583
4584   dest1 = gen_highpart (SImode, operands[0]);
4585   dest2 = gen_lowpart (SImode, operands[0]);
4586
4587   /* Swap the order in case of overlap.  */
4588   if (REGNO (dest1) == REGNO (operands[1]))
4589     {
4590       operands[2] = dest2;
4591       operands[3] = operands[1];
4592       operands[4] = dest1;
4593       operands[5] = const0_rtx;
4594     }
4595   else
4596     {
4597       operands[2] = dest1;
4598       operands[3] = const0_rtx;
4599       operands[4] = dest2;
4600       operands[5] = operands[1];
4601     }
4602 }")
4603
4604 ;; Simplify comparisons of extended values.
4605
4606 (define_insn "*cmp_zero_extendqisi2"
4607   [(set (reg:CC 100)
4608         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
4609                     (const_int 0)))]
4610   "! TARGET_LIVE_G0"
4611   "andcc\\t%0, 0xff, %%g0"
4612   [(set_attr "type" "compare")
4613    (set_attr "length" "1")])
4614
4615 (define_insn "*cmp_zero_qi"
4616   [(set (reg:CC 100)
4617         (compare:CC (match_operand:QI 0 "register_operand" "r")
4618                     (const_int 0)))]
4619   "! TARGET_LIVE_G0"
4620   "andcc\\t%0, 0xff, %%g0"
4621   [(set_attr "type" "compare")
4622    (set_attr "length" "1")])
4623
4624 (define_insn "*cmp_zero_extendqisi2_set"
4625   [(set (reg:CC 100)
4626         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
4627                     (const_int 0)))
4628    (set (match_operand:SI 0 "register_operand" "=r")
4629         (zero_extend:SI (match_dup 1)))]
4630   ""
4631   "andcc\\t%1, 0xff, %0"
4632   [(set_attr "type" "compare")
4633    (set_attr "length" "1")])
4634
4635 (define_insn "*cmp_zero_extendqisi2_andcc_set"
4636   [(set (reg:CC 100)
4637         (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
4638                             (const_int 255))
4639                     (const_int 0)))
4640    (set (match_operand:SI 0 "register_operand" "=r")
4641         (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
4642   ""
4643   "andcc\\t%1, 0xff, %0"
4644   [(set_attr "type" "compare")
4645    (set_attr "length" "1")])
4646
4647 (define_insn "*cmp_zero_extendqidi2"
4648   [(set (reg:CCX 100)
4649         (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
4650                      (const_int 0)))]
4651   "TARGET_ARCH64"
4652   "andcc\\t%0, 0xff, %%g0"
4653   [(set_attr "type" "compare")
4654    (set_attr "length" "1")])
4655
4656 (define_insn "*cmp_zero_qi_sp64"
4657   [(set (reg:CCX 100)
4658         (compare:CCX (match_operand:QI 0 "register_operand" "r")
4659                      (const_int 0)))]
4660   "TARGET_ARCH64"
4661   "andcc\\t%0, 0xff, %%g0"
4662   [(set_attr "type" "compare")
4663    (set_attr "length" "1")])
4664
4665 (define_insn "*cmp_zero_extendqidi2_set"
4666   [(set (reg:CCX 100)
4667         (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
4668                      (const_int 0)))
4669    (set (match_operand:DI 0 "register_operand" "=r")
4670         (zero_extend:DI (match_dup 1)))]
4671   "TARGET_ARCH64"
4672   "andcc\\t%1, 0xff, %0"
4673   [(set_attr "type" "compare")
4674    (set_attr "length" "1")])
4675
4676 (define_insn "*cmp_zero_extendqidi2_andcc_set"
4677   [(set (reg:CCX 100)
4678         (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
4679                              (const_int 255))
4680                      (const_int 0)))
4681    (set (match_operand:DI 0 "register_operand" "=r")
4682         (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
4683   "TARGET_ARCH64"
4684   "andcc\\t%1, 0xff, %0"
4685   [(set_attr "type" "compare")
4686    (set_attr "length" "1")])
4687
4688 ;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
4689
4690 (define_insn "*cmp_siqi_trunc"
4691   [(set (reg:CC 100)
4692         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
4693                     (const_int 0)))]
4694   "! TARGET_LIVE_G0"
4695   "andcc\\t%0, 0xff, %%g0"
4696   [(set_attr "type" "compare")
4697    (set_attr "length" "1")])
4698
4699 (define_insn "*cmp_siqi_trunc_set"
4700   [(set (reg:CC 100)
4701         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
4702                     (const_int 0)))
4703    (set (match_operand:QI 0 "register_operand" "=r")
4704         (subreg:QI (match_dup 1) 0))]
4705   ""
4706   "andcc\\t%1, 0xff, %0"
4707   [(set_attr "type" "compare")
4708    (set_attr "length" "1")])
4709
4710 (define_insn "*cmp_diqi_trunc"
4711   [(set (reg:CC 100)
4712         (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
4713                     (const_int 0)))]
4714   "TARGET_ARCH64"
4715   "andcc\\t%0, 0xff, %%g0"
4716   [(set_attr "type" "compare")
4717    (set_attr "length" "1")])
4718
4719 (define_insn "*cmp_diqi_trunc_set"
4720   [(set (reg:CC 100)
4721         (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
4722                     (const_int 0)))
4723    (set (match_operand:QI 0 "register_operand" "=r")
4724         (subreg:QI (match_dup 1) 0))]
4725   "TARGET_ARCH64"
4726   "andcc\\t%1, 0xff, %0"
4727   [(set_attr "type" "compare")
4728    (set_attr "length" "1")])
4729 \f
4730 ;;- sign extension instructions
4731
4732 ;; These patterns originally accepted general_operands, however, slightly
4733 ;; better code is generated by only accepting register_operands, and then
4734 ;; letting combine generate the lds[hb] insns.
4735
4736 (define_expand "extendhisi2"
4737   [(set (match_operand:SI 0 "register_operand" "")
4738         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4739   ""
4740   "
4741 {
4742   rtx temp = gen_reg_rtx (SImode);
4743   rtx shift_16 = GEN_INT (16);
4744   int op1_subword = 0;
4745
4746   if (GET_CODE (operand1) == SUBREG)
4747     {
4748       op1_subword = SUBREG_WORD (operand1);
4749       operand1 = XEXP (operand1, 0);
4750     }
4751
4752   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
4753                           shift_16));
4754   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
4755   DONE;
4756 }")
4757
4758 (define_insn "*sign_extendhisi2_insn"
4759   [(set (match_operand:SI 0 "register_operand" "=r")
4760         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4761   ""
4762   "ldsh\\t%1, %0"
4763   [(set_attr "type" "sload")
4764    (set_attr "length" "1")])
4765
4766 (define_expand "extendqihi2"
4767   [(set (match_operand:HI 0 "register_operand" "")
4768         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
4769   ""
4770   "
4771 {
4772   rtx temp = gen_reg_rtx (SImode);
4773   rtx shift_24 = GEN_INT (24);
4774   int op1_subword = 0;
4775   int op0_subword = 0;
4776
4777   if (GET_CODE (operand1) == SUBREG)
4778     {
4779       op1_subword = SUBREG_WORD (operand1);
4780       operand1 = XEXP (operand1, 0);
4781     }
4782   if (GET_CODE (operand0) == SUBREG)
4783     {
4784       op0_subword = SUBREG_WORD (operand0);
4785       operand0 = XEXP (operand0, 0);
4786     }
4787   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
4788                           shift_24));
4789   if (GET_MODE (operand0) != SImode)
4790     operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword);
4791   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4792   DONE;
4793 }")
4794
4795 (define_insn "*sign_extendqihi2_insn"
4796   [(set (match_operand:HI 0 "register_operand" "=r")
4797         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
4798   ""
4799   "ldsb\\t%1, %0"
4800   [(set_attr "type" "sload")
4801    (set_attr "length" "1")])
4802
4803 (define_expand "extendqisi2"
4804   [(set (match_operand:SI 0 "register_operand" "")
4805         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4806   ""
4807   "
4808 {
4809   rtx temp = gen_reg_rtx (SImode);
4810   rtx shift_24 = GEN_INT (24);
4811   int op1_subword = 0;
4812
4813   if (GET_CODE (operand1) == SUBREG)
4814     {
4815       op1_subword = SUBREG_WORD (operand1);
4816       operand1 = XEXP (operand1, 0);
4817     }
4818
4819   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
4820                           shift_24));
4821   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4822   DONE;
4823 }")
4824
4825 (define_insn "*sign_extendqisi2_insn"
4826   [(set (match_operand:SI 0 "register_operand" "=r")
4827         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4828   ""
4829   "ldsb\\t%1, %0"
4830   [(set_attr "type" "sload")
4831    (set_attr "length" "1")])
4832
4833 (define_expand "extendqidi2"
4834   [(set (match_operand:DI 0 "register_operand" "")
4835         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
4836   "TARGET_ARCH64"
4837   "
4838 {
4839   rtx temp = gen_reg_rtx (DImode);
4840   rtx shift_56 = GEN_INT (56);
4841   int op1_subword = 0;
4842
4843   if (GET_CODE (operand1) == SUBREG)
4844     {
4845       op1_subword = SUBREG_WORD (operand1);
4846       operand1 = XEXP (operand1, 0);
4847     }
4848
4849   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
4850                           shift_56));
4851   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
4852   DONE;
4853 }")
4854
4855 (define_insn "*sign_extendqidi2_insn"
4856   [(set (match_operand:DI 0 "register_operand" "=r")
4857         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
4858   "TARGET_ARCH64"
4859   "ldsb\\t%1, %0"
4860   [(set_attr "type" "sload")
4861    (set_attr "length" "1")])
4862
4863 (define_expand "extendhidi2"
4864   [(set (match_operand:DI 0 "register_operand" "")
4865         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
4866   "TARGET_ARCH64"
4867   "
4868 {
4869   rtx temp = gen_reg_rtx (DImode);
4870   rtx shift_48 = GEN_INT (48);
4871   int op1_subword = 0;
4872
4873   if (GET_CODE (operand1) == SUBREG)
4874     {
4875       op1_subword = SUBREG_WORD (operand1);
4876       operand1 = XEXP (operand1, 0);
4877     }
4878
4879   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
4880                           shift_48));
4881   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
4882   DONE;
4883 }")
4884
4885 (define_insn "*sign_extendhidi2_insn"
4886   [(set (match_operand:DI 0 "register_operand" "=r")
4887         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4888   "TARGET_ARCH64"
4889   "ldsh\\t%1, %0"
4890   [(set_attr "type" "sload")
4891    (set_attr "length" "1")])
4892
4893 (define_expand "extendsidi2"
4894   [(set (match_operand:DI 0 "register_operand" "")
4895         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
4896   "TARGET_ARCH64"
4897   "")
4898
4899 (define_insn "*sign_extendsidi2_insn"
4900   [(set (match_operand:DI 0 "register_operand" "=r,r")
4901         (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4902   "TARGET_ARCH64"
4903   "@
4904   sra\\t%1, 0, %0
4905   ldsw\\t%1, %0"
4906   [(set_attr "type" "shift,sload")
4907    (set_attr "length" "1")])
4908 \f
4909 ;; Special pattern for optimizing bit-field compares.  This is needed
4910 ;; because combine uses this as a canonical form.
4911
4912 (define_insn "*cmp_zero_extract"
4913   [(set (reg:CC 100)
4914         (compare:CC
4915          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
4916                           (match_operand:SI 1 "small_int_or_double" "n")
4917                           (match_operand:SI 2 "small_int_or_double" "n"))
4918          (const_int 0)))]
4919   "! TARGET_LIVE_G0
4920    && ((GET_CODE (operands[2]) == CONST_INT
4921         && INTVAL (operands[2]) > 19)
4922        || (GET_CODE (operands[2]) == CONST_DOUBLE
4923            && CONST_DOUBLE_LOW (operands[2]) > 19))"
4924   "*
4925 {
4926   int len = (GET_CODE (operands[1]) == CONST_INT
4927              ? INTVAL (operands[1])
4928              : CONST_DOUBLE_LOW (operands[1]));
4929   int pos = 32 -
4930             (GET_CODE (operands[2]) == CONST_INT
4931              ? INTVAL (operands[2])
4932              : CONST_DOUBLE_LOW (operands[2])) - len;
4933   HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
4934
4935   operands[1] = GEN_INT (mask);
4936   return \"andcc\\t%0, %1, %%g0\";
4937 }"
4938   [(set_attr "type" "compare")
4939    (set_attr "length" "1")])
4940
4941 (define_insn "*cmp_zero_extract_sp64"
4942   [(set (reg:CCX 100)
4943         (compare:CCX
4944          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
4945                           (match_operand:SI 1 "small_int_or_double" "n")
4946                           (match_operand:SI 2 "small_int_or_double" "n"))
4947          (const_int 0)))]
4948   "TARGET_ARCH64
4949    && ((GET_CODE (operands[2]) == CONST_INT
4950         && INTVAL (operands[2]) > 51)
4951        || (GET_CODE (operands[2]) == CONST_DOUBLE
4952            && CONST_DOUBLE_LOW (operands[2]) > 51))"
4953   "*
4954 {
4955   int len = (GET_CODE (operands[1]) == CONST_INT
4956              ? INTVAL (operands[1])
4957              : CONST_DOUBLE_LOW (operands[1]));
4958   int pos = 64 -
4959             (GET_CODE (operands[2]) == CONST_INT
4960              ? INTVAL (operands[2])
4961              : CONST_DOUBLE_LOW (operands[2])) - len;
4962   HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
4963
4964   operands[1] = GEN_INT (mask);
4965   return \"andcc\\t%0, %1, %%g0\";
4966 }"
4967   [(set_attr "type" "compare")
4968    (set_attr "length" "1")])
4969 \f
4970 ;; Conversions between float, double and long double.
4971
4972 (define_insn "extendsfdf2"
4973   [(set (match_operand:DF 0 "register_operand" "=e")
4974         (float_extend:DF
4975          (match_operand:SF 1 "register_operand" "f")))]
4976   "TARGET_FPU"
4977   "fstod\\t%1, %0"
4978   [(set_attr "type" "fp")
4979    (set_attr "length" "1")])
4980
4981 (define_expand "extendsftf2"
4982   [(set (match_operand:TF 0 "register_operand" "=e")
4983         (float_extend:TF
4984          (match_operand:SF 1 "register_operand" "f")))]
4985   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4986   "
4987 {
4988   if (! TARGET_HARD_QUAD)
4989     {
4990       rtx slot0;
4991
4992       if (GET_CODE (operands[0]) != MEM)
4993         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
4994       else
4995         slot0 = operands[0];
4996
4997       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_stoq\"), 0,
4998                          VOIDmode, 2,
4999                          XEXP (slot0, 0), Pmode,
5000                          operands[1], SFmode);
5001
5002       if (GET_CODE (operands[0]) != MEM)
5003         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5004       DONE;
5005     }
5006 }")
5007
5008 (define_insn "*extendsftf2_hq"
5009   [(set (match_operand:TF 0 "register_operand" "=e")
5010         (float_extend:TF
5011          (match_operand:SF 1 "register_operand" "f")))]
5012   "TARGET_FPU && TARGET_HARD_QUAD"
5013   "fstoq\\t%1, %0"
5014   [(set_attr "type" "fp")
5015    (set_attr "length" "1")])
5016
5017 (define_expand "extenddftf2"
5018   [(set (match_operand:TF 0 "register_operand" "=e")
5019         (float_extend:TF
5020          (match_operand:DF 1 "register_operand" "e")))]
5021   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5022   "
5023 {
5024   if (! TARGET_HARD_QUAD)
5025     {
5026       rtx slot0;
5027
5028       if (GET_CODE (operands[0]) != MEM)
5029         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5030       else
5031         slot0 = operands[0];
5032
5033       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_dtoq\"), 0,
5034                          VOIDmode, 2,
5035                          XEXP (slot0, 0), Pmode,
5036                          operands[1], DFmode);
5037
5038       if (GET_CODE (operands[0]) != MEM)
5039         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5040       DONE;
5041     }
5042 }")
5043
5044 (define_insn "*extenddftf2_hq"
5045   [(set (match_operand:TF 0 "register_operand" "=e")
5046         (float_extend:TF
5047          (match_operand:DF 1 "register_operand" "e")))]
5048   "TARGET_FPU && TARGET_HARD_QUAD"
5049   "fdtoq\\t%1, %0"
5050   [(set_attr "type" "fp")
5051    (set_attr "length" "1")])
5052
5053 (define_insn "truncdfsf2"
5054   [(set (match_operand:SF 0 "register_operand" "=f")
5055         (float_truncate:SF
5056          (match_operand:DF 1 "register_operand" "e")))]
5057   "TARGET_FPU"
5058   "fdtos\\t%1, %0"
5059   [(set_attr "type" "fp")
5060    (set_attr "length" "1")])
5061
5062 (define_expand "trunctfsf2"
5063   [(set (match_operand:SF 0 "register_operand" "=f")
5064         (float_truncate:SF
5065          (match_operand:TF 1 "register_operand" "e")))]
5066   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5067   "
5068 {
5069   if (! TARGET_HARD_QUAD)
5070     {
5071       rtx slot0;
5072
5073       if (GET_CODE (operands[1]) != MEM)
5074         {
5075           slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5076           emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5077         }
5078       else
5079         slot0 = operands[1];
5080
5081       emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtos\"),
5082                                operands[0], 0, SFmode, 1,
5083                                XEXP (slot0, 0), Pmode);
5084       DONE;
5085     }
5086 }")
5087
5088 (define_insn "*trunctfsf2_hq"
5089   [(set (match_operand:SF 0 "register_operand" "=f")
5090         (float_truncate:SF
5091          (match_operand:TF 1 "register_operand" "e")))]
5092   "TARGET_FPU && TARGET_HARD_QUAD"
5093   "fqtos\\t%1, %0"
5094   [(set_attr "type" "fp")
5095    (set_attr "length" "1")])
5096
5097 (define_expand "trunctfdf2"
5098   [(set (match_operand:DF 0 "register_operand" "=f")
5099         (float_truncate:DF
5100          (match_operand:TF 1 "register_operand" "e")))]
5101   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5102   "
5103 {
5104   if (! TARGET_HARD_QUAD)
5105     {
5106       rtx slot0;
5107
5108       if (GET_CODE (operands[1]) != MEM)
5109         {
5110           slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5111           emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5112         }
5113       else
5114         slot0 = operands[1];
5115
5116       emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtod\"),
5117                                operands[0], 0, DFmode, 1,
5118                                XEXP (slot0, 0), Pmode);
5119       DONE;
5120     }
5121 }")
5122
5123 (define_insn "*trunctfdf2_hq"
5124   [(set (match_operand:DF 0 "register_operand" "=e")
5125         (float_truncate:DF
5126          (match_operand:TF 1 "register_operand" "e")))]
5127   "TARGET_FPU && TARGET_HARD_QUAD"
5128   "fqtod\\t%1, %0"
5129   [(set_attr "type" "fp")
5130    (set_attr "length" "1")])
5131 \f
5132 ;; Conversion between fixed point and floating point.
5133
5134 (define_insn "floatsisf2"
5135   [(set (match_operand:SF 0 "register_operand" "=f")
5136         (float:SF (match_operand:SI 1 "register_operand" "f")))]
5137   "TARGET_FPU"
5138   "fitos\\t%1, %0"
5139   [(set_attr "type" "fp")
5140    (set_attr "length" "1")])
5141
5142 (define_insn "floatsidf2"
5143   [(set (match_operand:DF 0 "register_operand" "=e")
5144         (float:DF (match_operand:SI 1 "register_operand" "f")))]
5145   "TARGET_FPU"
5146   "fitod\\t%1, %0"
5147   [(set_attr "type" "fp")
5148    (set_attr "length" "1")])
5149
5150 (define_expand "floatsitf2"
5151   [(set (match_operand:TF 0 "register_operand" "=e")
5152         (float:TF (match_operand:SI 1 "register_operand" "f")))]
5153   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5154   "
5155 {
5156   if (! TARGET_HARD_QUAD)
5157     {
5158       rtx slot0;
5159
5160       if (GET_CODE (operands[1]) != MEM)
5161         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5162       else
5163         slot0 = operands[1];
5164
5165       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_itoq\"), 0,
5166                          VOIDmode, 2,
5167                          XEXP (slot0, 0), Pmode,
5168                          operands[1], SImode);
5169
5170       if (GET_CODE (operands[0]) != MEM)
5171         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5172       DONE;
5173     }
5174 }")
5175
5176 (define_insn "*floatsitf2_hq"
5177   [(set (match_operand:TF 0 "register_operand" "=e")
5178         (float:TF (match_operand:SI 1 "register_operand" "f")))]
5179   "TARGET_FPU && TARGET_HARD_QUAD"
5180   "fitoq\\t%1, %0"
5181   [(set_attr "type" "fp")
5182    (set_attr "length" "1")])
5183
5184 (define_expand "floatunssitf2"
5185   [(set (match_operand:TF 0 "register_operand" "=e")
5186         (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
5187   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
5188   "
5189 {
5190   rtx slot0;
5191
5192   if (GET_CODE (operands[1]) != MEM)
5193     slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5194   else
5195     slot0 = operands[1];
5196
5197   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uitoq\"), 0,
5198                      VOIDmode, 2,
5199                      XEXP (slot0, 0), Pmode,
5200                      operands[1], SImode);
5201
5202   if (GET_CODE (operands[0]) != MEM)
5203     emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5204   DONE;
5205 }")
5206
5207 ;; Now the same for 64 bit sources.
5208
5209 (define_insn "floatdisf2"
5210   [(set (match_operand:SF 0 "register_operand" "=f")
5211         (float:SF (match_operand:DI 1 "register_operand" "e")))]
5212   "TARGET_V9 && TARGET_FPU"
5213   "fxtos\\t%1, %0"
5214   [(set_attr "type" "fp")
5215    (set_attr "length" "1")])
5216
5217 (define_insn "floatdidf2"
5218   [(set (match_operand:DF 0 "register_operand" "=e")
5219         (float:DF (match_operand:DI 1 "register_operand" "e")))]
5220   "TARGET_V9 && TARGET_FPU"
5221   "fxtod\\t%1, %0"
5222   [(set_attr "type" "fp")
5223    (set_attr "length" "1")])
5224
5225 (define_expand "floatditf2"
5226   [(set (match_operand:TF 0 "register_operand" "=e")
5227         (float:TF (match_operand:DI 1 "register_operand" "e")))]
5228   "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5229   "
5230 {
5231   if (! TARGET_HARD_QUAD)
5232     {
5233       rtx slot0;
5234
5235       if (GET_CODE (operands[1]) != MEM)
5236         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5237       else
5238         slot0 = operands[1];
5239
5240       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_xtoq\"), 0,
5241                          VOIDmode, 2,
5242                          XEXP (slot0, 0), Pmode,
5243                          operands[1], DImode);
5244
5245       if (GET_CODE (operands[0]) != MEM)
5246         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5247       DONE;
5248     }
5249 }")
5250
5251 (define_insn "*floatditf2_hq"
5252   [(set (match_operand:TF 0 "register_operand" "=e")
5253         (float:TF (match_operand:DI 1 "register_operand" "e")))]
5254   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
5255   "fxtoq\\t%1, %0"
5256   [(set_attr "type" "fp")
5257    (set_attr "length" "1")])
5258
5259 (define_expand "floatunsditf2"
5260   [(set (match_operand:TF 0 "register_operand" "=e")
5261         (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
5262   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
5263   "
5264 {
5265   rtx slot0;
5266
5267   if (GET_CODE (operands[1]) != MEM)
5268     slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5269   else
5270     slot0 = operands[1];
5271
5272   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uxtoq\"), 0,
5273                      VOIDmode, 2,
5274                      XEXP (slot0, 0), Pmode,
5275                      operands[1], DImode);
5276
5277   if (GET_CODE (operands[0]) != MEM)
5278     emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
5279   DONE;
5280 }")
5281
5282 ;; Convert a float to an actual integer.
5283 ;; Truncation is performed as part of the conversion.
5284
5285 (define_insn "fix_truncsfsi2"
5286   [(set (match_operand:SI 0 "register_operand" "=f")
5287         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
5288   "TARGET_FPU"
5289   "fstoi\\t%1, %0"
5290   [(set_attr "type" "fp")
5291    (set_attr "length" "1")])
5292
5293 (define_insn "fix_truncdfsi2"
5294   [(set (match_operand:SI 0 "register_operand" "=f")
5295         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
5296   "TARGET_FPU"
5297   "fdtoi\\t%1, %0"
5298   [(set_attr "type" "fp")
5299    (set_attr "length" "1")])
5300
5301 (define_expand "fix_trunctfsi2"
5302   [(set (match_operand:SI 0 "register_operand" "=f")
5303         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5304   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5305   "
5306 {
5307   if (! TARGET_HARD_QUAD)
5308     {
5309       rtx slot0;
5310
5311       if (GET_CODE (operands[1]) != MEM)
5312         {
5313           slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5314           emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5315         }
5316       else
5317         slot0 = operands[1];
5318
5319       emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
5320                                operands[0], 0, SImode, 1,
5321                                XEXP (slot0, 0), Pmode);
5322       DONE;
5323     }
5324 }")
5325
5326 (define_insn "*fix_trunctfsi2_hq"
5327   [(set (match_operand:SI 0 "register_operand" "=f")
5328         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5329   "TARGET_FPU && TARGET_HARD_QUAD"
5330   "fqtoi\\t%1, %0"
5331   [(set_attr "type" "fp")
5332    (set_attr "length" "1")])
5333
5334 (define_expand "fixuns_trunctfsi2"
5335   [(set (match_operand:SI 0 "register_operand" "=f")
5336         (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5337   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
5338   "
5339 {
5340   rtx slot0;
5341
5342   if (GET_CODE (operands[1]) != MEM)
5343     {
5344       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5345       emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5346     }
5347   else
5348     slot0 = operands[1];
5349
5350   emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
5351                            operands[0], 0, SImode, 1,
5352                            XEXP (slot0, 0), Pmode);
5353   DONE;
5354 }")
5355
5356 ;; Now the same, for V9 targets
5357
5358 (define_insn "fix_truncsfdi2"
5359   [(set (match_operand:DI 0 "register_operand" "=e")
5360         (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
5361   "TARGET_V9 && TARGET_FPU"
5362   "fstox\\t%1, %0"
5363   [(set_attr "type" "fp")
5364    (set_attr "length" "1")])
5365
5366 (define_insn "fix_truncdfdi2"
5367   [(set (match_operand:DI 0 "register_operand" "=e")
5368         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
5369   "TARGET_V9 && TARGET_FPU"
5370   "fdtox\\t%1, %0"
5371   [(set_attr "type" "fp")
5372    (set_attr "length" "1")])
5373
5374 (define_expand "fix_trunctfdi2"
5375   [(set (match_operand:DI 0 "register_operand" "=e")
5376         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5377   "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
5378   "
5379 {
5380   if (! TARGET_HARD_QUAD)
5381     {
5382       rtx slot0;
5383
5384       if (GET_CODE (operands[1]) != MEM)
5385         {
5386           slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5387           emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5388         }
5389       else
5390         slot0 = operands[1];
5391
5392       emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
5393                                operands[0], 0, DImode, 1,
5394                                XEXP (slot0, 0), Pmode);
5395       DONE;
5396     }
5397 }")
5398
5399 (define_insn "*fix_trunctfdi2_hq"
5400   [(set (match_operand:DI 0 "register_operand" "=e")
5401         (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5402   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
5403   "fqtox\\t%1, %0"
5404   [(set_attr "type" "fp")
5405    (set_attr "length" "1")])
5406
5407 (define_expand "fixuns_trunctfdi2"
5408   [(set (match_operand:DI 0 "register_operand" "=f")
5409         (unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
5410   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
5411   "
5412 {
5413   rtx slot0;
5414
5415   if (GET_CODE (operands[1]) != MEM)
5416     {
5417       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
5418       emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
5419     }
5420   else
5421     slot0 = operands[1];
5422
5423   emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoux\"),
5424                            operands[0], 0, DImode, 1,
5425                            XEXP (slot0, 0), Pmode);
5426   DONE;
5427 }")
5428
5429 \f
5430 ;;- arithmetic instructions
5431
5432 (define_expand "adddi3"
5433   [(set (match_operand:DI 0 "register_operand" "=r")
5434         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5435                  (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
5436   ""
5437   "
5438 {
5439   if (! TARGET_ARCH64)
5440     {
5441       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
5442                           gen_rtx_SET (VOIDmode, operands[0],
5443                                    gen_rtx_PLUS (DImode, operands[1],
5444                                                  operands[2])),
5445                           gen_rtx_CLOBBER (VOIDmode,
5446                                    gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
5447       DONE;
5448     }
5449   if (arith_double_4096_operand(operands[2], DImode))
5450     {
5451       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5452                               gen_rtx_MINUS (DImode, operands[1],
5453                                              GEN_INT(-4096))));
5454       DONE;
5455     }
5456 }")
5457
5458 (define_insn "adddi3_insn_sp32"
5459   [(set (match_operand:DI 0 "register_operand" "=r")
5460         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5461                  (match_operand:DI 2 "arith_double_operand" "rHI")))
5462    (clobber (reg:CC 100))]
5463   "! TARGET_ARCH64"
5464   "#"
5465   [(set_attr "length" "2")])
5466
5467 (define_split
5468   [(set (match_operand:DI 0 "register_operand" "=r")
5469         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5470                  (match_operand:DI 2 "arith_double_operand" "rHI")))
5471    (clobber (reg:CC 100))]
5472   "! TARGET_ARCH64 && reload_completed"
5473   [(parallel [(set (reg:CC_NOOV 100)
5474                    (compare:CC_NOOV (plus:SI (match_dup 4)
5475                                              (match_dup 5))
5476                                     (const_int 0)))
5477               (set (match_dup 3)
5478                    (plus:SI (match_dup 4) (match_dup 5)))])
5479    (set (match_dup 6)
5480         (plus:SI (plus:SI (match_dup 7)
5481                           (match_dup 8))
5482                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5483   "
5484 {
5485   operands[3] = gen_lowpart (SImode, operands[0]);
5486   operands[4] = gen_lowpart (SImode, operands[1]);
5487   operands[5] = gen_lowpart (SImode, operands[2]);
5488   operands[6] = gen_highpart (SImode, operands[0]);
5489   operands[7] = gen_highpart (SImode, operands[1]);
5490   if (GET_CODE (operands[2]) == CONST_INT)
5491     {
5492       if (INTVAL (operands[2]) < 0)
5493         operands[8] = constm1_rtx;
5494       else
5495         operands[8] = const0_rtx;
5496     }
5497   else
5498     operands[8] = gen_highpart (SImode, operands[2]);
5499 }")
5500
5501 (define_split
5502   [(set (match_operand:DI 0 "register_operand" "=r")
5503         (minus:DI (match_operand:DI 1 "arith_double_operand" "r")
5504                   (match_operand:DI 2 "arith_double_operand" "rHI")))
5505    (clobber (reg:CC 100))]
5506   "! TARGET_ARCH64 && reload_completed"
5507   [(parallel [(set (reg:CC_NOOV 100)
5508                    (compare:CC_NOOV (minus:SI (match_dup 4)
5509                                               (match_dup 5))
5510                                     (const_int 0)))
5511               (set (match_dup 3)
5512                    (minus:SI (match_dup 4) (match_dup 5)))])
5513    (set (match_dup 6)
5514         (minus:SI (minus:SI (match_dup 7)
5515                             (match_dup 8))
5516                   (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5517   "
5518 {
5519   operands[3] = gen_lowpart (SImode, operands[0]);
5520   operands[4] = gen_lowpart (SImode, operands[1]);
5521   operands[5] = gen_lowpart (SImode, operands[2]);
5522   operands[6] = gen_highpart (SImode, operands[0]);
5523   operands[7] = gen_highpart (SImode, operands[1]);
5524   if (GET_CODE (operands[2]) == CONST_INT)
5525     {
5526       if (INTVAL (operands[2]) < 0)
5527         operands[8] = constm1_rtx;
5528       else
5529         operands[8] = const0_rtx;
5530     }
5531   else
5532     operands[8] = gen_highpart (SImode, operands[2]);
5533 }")
5534
5535 ;; LTU here means "carry set"
5536 (define_insn "addx"
5537   [(set (match_operand:SI 0 "register_operand" "=r")
5538         (plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
5539                           (match_operand:SI 2 "arith_operand" "rI"))
5540                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5541   ""
5542   "addx\\t%1, %2, %0"
5543   [(set_attr "type" "unary")
5544    (set_attr "length" "1")])
5545
5546 (define_insn "*addx_extend_sp32"
5547   [(set (match_operand:DI 0 "register_operand" "=r")
5548         (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
5549                                           (match_operand:SI 2 "arith_operand" "rI"))
5550                                  (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5551   "! TARGET_ARCH64"
5552   "#"
5553   [(set_attr "type" "unary")
5554    (set_attr "length" "2")])
5555
5556 (define_split
5557   [(set (match_operand:DI 0 "register_operand" "")
5558         (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "")
5559                                           (match_operand:SI 2 "arith_operand" ""))
5560                                  (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5561   "! TARGET_ARCH64 && reload_completed"
5562   [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
5563                                (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
5564    (set (match_dup 4) (const_int 0))]
5565   "operands[3] = gen_lowpart (SImode, operands[0]);
5566    operands[4] = gen_highpart (SImode, operands[1]);")
5567
5568 (define_insn "*addx_extend_sp64"
5569   [(set (match_operand:DI 0 "register_operand" "=r")
5570         (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
5571                                           (match_operand:SI 2 "arith_operand" "rI"))
5572                                  (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5573   "TARGET_ARCH64"
5574   "addx\\t%r1, %2, %0"
5575   [(set_attr "type" "misc")
5576    (set_attr "length" "1")])
5577
5578 (define_insn "subx"
5579   [(set (match_operand:SI 0 "register_operand" "=r")
5580         (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5581                             (match_operand:SI 2 "arith_operand" "rI"))
5582                   (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5583   ""
5584   "subx\\t%r1, %2, %0"
5585   [(set_attr "type" "misc")
5586    (set_attr "length" "1")])
5587
5588 (define_insn "*subx_extend_sp64"
5589   [(set (match_operand:DI 0 "register_operand" "=r")
5590         (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5591                                             (match_operand:SI 2 "arith_operand" "rI"))
5592                                   (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5593   "TARGET_ARCH64"
5594   "subx\\t%r1, %2, %0"
5595   [(set_attr "type" "misc")
5596    (set_attr "length" "1")])
5597
5598 (define_insn "*subx_extend"
5599   [(set (match_operand:DI 0 "register_operand" "=r")
5600         (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5601                                             (match_operand:SI 2 "arith_operand" "rI"))
5602                                   (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5603   "! TARGET_ARCH64"
5604   "#"
5605   [(set_attr "type" "unary")
5606    (set_attr "length" "2")])
5607
5608 (define_split
5609   [(set (match_operand:DI 0 "register_operand" "=r")
5610         (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5611                                             (match_operand:SI 2 "arith_operand" "rI"))
5612                                   (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
5613   "! TARGET_ARCH64 && reload_completed"
5614   [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
5615                                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
5616    (set (match_dup 4) (const_int 0))]
5617   "operands[3] = gen_lowpart (SImode, operands[0]);
5618    operands[4] = gen_highpart (SImode, operands[0]);")
5619
5620 (define_insn ""
5621   [(set (match_operand:DI 0 "register_operand" "=r")
5622         (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5623                  (match_operand:DI 2 "register_operand" "r")))
5624    (clobber (reg:CC 100))]
5625   "! TARGET_ARCH64"
5626   "#"
5627   [(set_attr "type" "multi")
5628    (set_attr "length" "2")])
5629
5630 (define_split
5631   [(set (match_operand:DI 0 "register_operand" "")
5632         (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5633                  (match_operand:DI 2 "register_operand" "")))
5634    (clobber (reg:CC 100))]
5635   "! TARGET_ARCH64 && reload_completed"
5636   [(parallel [(set (reg:CC_NOOV 100)
5637                    (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
5638                                     (const_int 0)))
5639               (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
5640    (set (match_dup 6)
5641         (plus:SI (plus:SI (match_dup 4) (const_int 0))
5642                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5643   "operands[3] = gen_lowpart (SImode, operands[2]);
5644    operands[4] = gen_highpart (SImode, operands[2]);
5645    operands[5] = gen_lowpart (SImode, operands[0]);
5646    operands[6] = gen_highpart (SImode, operands[0]);")
5647
5648 (define_insn "*adddi3_sp64"
5649   [(set (match_operand:DI 0 "register_operand" "=r")
5650         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5651                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
5652   "TARGET_ARCH64"
5653   "add\\t%1, %2, %0"
5654   [(set_attr "type" "binary")
5655    (set_attr "length" "1")])
5656
5657 (define_expand "addsi3"
5658   [(set (match_operand:SI 0 "register_operand" "=r,d")
5659         (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
5660                  (match_operand:SI 2 "arith_add_operand" "rI,d")))]
5661   ""
5662   "
5663 {
5664   if (arith_4096_operand(operands[2], DImode))
5665     {
5666       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5667                               gen_rtx_MINUS (SImode, operands[1],
5668                                              GEN_INT(-4096))));
5669       DONE;
5670     }
5671 }")
5672
5673 (define_insn "*addsi3"
5674   [(set (match_operand:SI 0 "register_operand" "=r,d")
5675         (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
5676                  (match_operand:SI 2 "arith_operand" "rI,d")))]
5677   ""
5678   "@
5679    add\\t%1, %2, %0
5680    fpadd32s\\t%1, %2, %0"
5681   [(set_attr "type" "ialu,fp")
5682    (set_attr "length" "1")])
5683
5684 (define_insn "*cmp_cc_plus"
5685   [(set (reg:CC_NOOV 100)
5686         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
5687                                   (match_operand:SI 1 "arith_operand" "rI"))
5688                          (const_int 0)))]
5689   "! TARGET_LIVE_G0"
5690   "addcc\\t%0, %1, %%g0"
5691   [(set_attr "type" "compare")
5692    (set_attr "length" "1")])
5693
5694 (define_insn "*cmp_ccx_plus"
5695   [(set (reg:CCX_NOOV 100)
5696         (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
5697                                    (match_operand:DI 1 "arith_double_operand" "rHI"))
5698                           (const_int 0)))]
5699   "TARGET_ARCH64"
5700   "addcc\\t%0, %1, %%g0"
5701   [(set_attr "type" "compare")
5702    (set_attr "length" "1")])
5703
5704 (define_insn "*cmp_cc_plus_set"
5705   [(set (reg:CC_NOOV 100)
5706         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
5707                                   (match_operand:SI 2 "arith_operand" "rI"))
5708                          (const_int 0)))
5709    (set (match_operand:SI 0 "register_operand" "=r")
5710         (plus:SI (match_dup 1) (match_dup 2)))]
5711   ""
5712   "addcc\\t%1, %2, %0"
5713   [(set_attr "type" "compare")
5714    (set_attr "length" "1")])
5715
5716 (define_insn "*cmp_ccx_plus_set"
5717   [(set (reg:CCX_NOOV 100)
5718         (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5719                                    (match_operand:DI 2 "arith_double_operand" "rHI"))
5720                           (const_int 0)))
5721    (set (match_operand:DI 0 "register_operand" "=r")
5722         (plus:DI (match_dup 1) (match_dup 2)))]
5723   "TARGET_ARCH64"
5724   "addcc\\t%1, %2, %0"
5725   [(set_attr "type" "compare")
5726    (set_attr "length" "1")])
5727
5728 (define_expand "subdi3"
5729   [(set (match_operand:DI 0 "register_operand" "=r")
5730         (minus:DI (match_operand:DI 1 "register_operand" "r")
5731                   (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
5732   ""
5733   "
5734 {
5735   if (! TARGET_ARCH64)
5736     {
5737       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
5738                           gen_rtx_SET (VOIDmode, operands[0],
5739                                    gen_rtx_MINUS (DImode, operands[1],
5740                                                   operands[2])),
5741                           gen_rtx_CLOBBER (VOIDmode,
5742                                    gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
5743       DONE;
5744     }
5745   if (arith_double_4096_operand(operands[2], DImode))
5746     {
5747       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5748                               gen_rtx_PLUS (DImode, operands[1],
5749                                             GEN_INT(-4096))));
5750       DONE;
5751     }
5752 }")
5753
5754 (define_insn "*subdi3_sp32"
5755   [(set (match_operand:DI 0 "register_operand" "=r")
5756         (minus:DI (match_operand:DI 1 "register_operand" "r")
5757                   (match_operand:DI 2 "arith_double_operand" "rHI")))
5758    (clobber (reg:CC 100))]
5759   "! TARGET_ARCH64"
5760   "#"
5761   [(set_attr "length" "2")])
5762
5763 (define_split
5764   [(set (match_operand:DI 0 "register_operand" "")
5765         (minus:DI (match_operand:DI 1 "register_operand" "")
5766                   (match_operand:DI 2 "arith_double_operand" "")))
5767    (clobber (reg:CC 100))]
5768   "! TARGET_ARCH64
5769    && reload_completed
5770    && (GET_CODE (operands[2]) == CONST_INT
5771        || GET_CODE (operands[2]) == CONST_DOUBLE)"
5772   [(clobber (const_int 0))]
5773   "
5774 {
5775   rtx highp, lowp;
5776
5777   highp = gen_highpart (SImode, operands[2]);
5778   lowp = gen_lowpart (SImode, operands[2]);
5779   if ((lowp == const0_rtx)
5780       && (operands[0] == operands[1]))
5781     {
5782       emit_insn (gen_rtx_SET (VOIDmode,
5783                               gen_highpart (SImode, operands[0]),
5784                               gen_rtx_MINUS (SImode,
5785                                              gen_highpart (SImode, operands[1]),
5786                                              highp)));
5787     }
5788   else
5789     {
5790       emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5791                                        gen_lowpart (SImode, operands[1]),
5792                                        lowp));
5793       emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5794                            gen_highpart (SImode, operands[1]),
5795                            highp));
5796     }
5797   DONE;
5798 }")
5799
5800 (define_split
5801   [(set (match_operand:DI 0 "register_operand" "")
5802         (minus:DI (match_operand:DI 1 "register_operand" "")
5803                   (match_operand:DI 2 "register_operand" "")))
5804    (clobber (reg:CC 100))]
5805   "! TARGET_ARCH64
5806    && reload_completed"
5807   [(clobber (const_int 0))]
5808   "
5809 {
5810   emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5811                                    gen_lowpart (SImode, operands[1]),
5812                                    gen_lowpart (SImode, operands[2])));
5813   emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5814                        gen_highpart (SImode, operands[1]),
5815                        gen_highpart (SImode, operands[2])));
5816   DONE;
5817 }")
5818
5819 (define_insn ""
5820   [(set (match_operand:DI 0 "register_operand" "=r")
5821       (minus:DI (match_operand:DI 1 "register_operand" "r")
5822                 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
5823    (clobber (reg:CC 100))]
5824   "! TARGET_ARCH64"
5825   "#"
5826   [(set_attr "type" "multi")
5827    (set_attr "length" "2")])
5828
5829 (define_split
5830   [(set (match_operand:DI 0 "register_operand" "")
5831         (minus:DI (match_operand:DI 1 "register_operand" "")
5832                   (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
5833    (clobber (reg:CC 100))]
5834   "! TARGET_ARCH64 && reload_completed"
5835   [(parallel [(set (reg:CC_NOOV 100)
5836                    (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
5837                                     (const_int 0)))
5838               (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
5839    (set (match_dup 6)
5840         (minus:SI (minus:SI (match_dup 4) (const_int 0))
5841                   (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5842   "operands[3] = gen_lowpart (SImode, operands[1]);
5843    operands[4] = gen_highpart (SImode, operands[1]);
5844    operands[5] = gen_lowpart (SImode, operands[0]);
5845    operands[6] = gen_highpart (SImode, operands[0]);")
5846
5847 (define_insn "*subdi3_sp64"
5848   [(set (match_operand:DI 0 "register_operand" "=r")
5849         (minus:DI (match_operand:DI 1 "register_operand" "r")
5850                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
5851   "TARGET_ARCH64"
5852   "sub\\t%1, %2, %0"
5853   [(set_attr "type" "binary")
5854    (set_attr "length" "1")])
5855
5856 (define_expand "subsi3"
5857   [(set (match_operand:SI 0 "register_operand" "=r,d")
5858         (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5859                   (match_operand:SI 2 "arith_add_operand" "rI,d")))]
5860   ""
5861   "
5862 {
5863   if (arith_4096_operand(operands[2], DImode))
5864     {
5865       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
5866                               gen_rtx_PLUS (SImode, operands[1],
5867                                             GEN_INT(-4096))));
5868       DONE;
5869     }
5870 }")
5871
5872 (define_insn "*subsi3"
5873   [(set (match_operand:SI 0 "register_operand" "=r,d")
5874         (minus:SI (match_operand:SI 1 "register_operand" "r,d")
5875                   (match_operand:SI 2 "arith_operand" "rI,d")))]
5876   ""
5877   "@
5878    sub\\t%1, %2, %0
5879    fpsub32s\\t%1, %2, %0"
5880   [(set_attr "type" "ialu,fp")
5881    (set_attr "length" "1")])
5882
5883 (define_insn "*cmp_minus_cc"
5884   [(set (reg:CC_NOOV 100)
5885         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
5886                                    (match_operand:SI 1 "arith_operand" "rI"))
5887                          (const_int 0)))]
5888   "! TARGET_LIVE_G0"
5889   "subcc\\t%r0, %1, %%g0"
5890   [(set_attr "type" "compare")
5891    (set_attr "length" "1")])
5892
5893 (define_insn "*cmp_minus_ccx"
5894   [(set (reg:CCX_NOOV 100)
5895         (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
5896                                     (match_operand:DI 1 "arith_double_operand" "rHI"))
5897                           (const_int 0)))]
5898   "TARGET_ARCH64"
5899   "subcc\\t%0, %1, %%g0"
5900   [(set_attr "type" "compare")
5901    (set_attr "length" "1")])
5902
5903 (define_insn "cmp_minus_cc_set"
5904   [(set (reg:CC_NOOV 100)
5905         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5906                                    (match_operand:SI 2 "arith_operand" "rI"))
5907                          (const_int 0)))
5908    (set (match_operand:SI 0 "register_operand" "=r")
5909         (minus:SI (match_dup 1) (match_dup 2)))]
5910   ""
5911   "subcc\\t%r1, %2, %0"
5912   [(set_attr "type" "compare")
5913    (set_attr "length" "1")])
5914
5915 (define_insn "*cmp_minus_ccx_set"
5916   [(set (reg:CCX_NOOV 100)
5917         (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
5918                                     (match_operand:DI 2 "arith_double_operand" "rHI"))
5919                           (const_int 0)))
5920    (set (match_operand:DI 0 "register_operand" "=r")
5921         (minus:DI (match_dup 1) (match_dup 2)))]
5922   "TARGET_ARCH64"
5923   "subcc\\t%1, %2, %0"
5924   [(set_attr "type" "compare")
5925    (set_attr "length" "1")])
5926 \f
5927 ;; Integer Multiply/Divide.
5928
5929 ;; The 32 bit multiply/divide instructions are deprecated on v9, but at
5930 ;; least in UltraSPARC I, II and IIi it is a win tick-wise.
5931
5932 (define_insn "mulsi3"
5933   [(set (match_operand:SI 0 "register_operand" "=r")
5934         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5935                  (match_operand:SI 2 "arith_operand" "rI")))]
5936   "TARGET_HARD_MUL"
5937   "smul\\t%1, %2, %0"
5938   [(set_attr "type" "imul")
5939    (set_attr "length" "1")])
5940
5941 (define_expand "muldi3"
5942   [(set (match_operand:DI 0 "register_operand" "=r")
5943         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5944                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
5945   "TARGET_ARCH64 || TARGET_V8PLUS"
5946   "
5947 {
5948   if (TARGET_V8PLUS)
5949     {
5950       emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
5951       DONE;
5952     }
5953 }")
5954
5955 (define_insn "*muldi3_sp64"
5956   [(set (match_operand:DI 0 "register_operand" "=r")
5957         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5958                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
5959   "TARGET_ARCH64"
5960   "mulx\\t%1, %2, %0"
5961   [(set_attr "type" "imul")
5962    (set_attr "length" "1")])
5963
5964 ;; V8plus wide multiply.
5965 ;; XXX
5966 (define_insn "muldi3_v8plus"
5967   [(set (match_operand:DI 0 "register_operand" "=r,h")
5968         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
5969                  (match_operand:DI 2 "arith_double_operand" "rHI,rHI")))
5970    (clobber (match_scratch:SI 3 "=&h,X"))
5971    (clobber (match_scratch:SI 4 "=&h,X"))]
5972   "TARGET_V8PLUS"
5973   "*
5974 {
5975   if (sparc_check_64 (operands[1], insn) <= 0)
5976     output_asm_insn (\"srl\\t%L1, 0, %L1\", operands);
5977   if (which_alternative == 1)
5978     output_asm_insn (\"sllx\\t%H1, 32, %H1\", operands);
5979   if (sparc_check_64 (operands[2], insn) <= 0)
5980     output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
5981   if (which_alternative == 1)
5982     return \"or\\t%L1, %H1, %H1\\n\\tsllx\\t%H2, 32, %L1\\n\\tor\\t%L2, %L1, %L1\\n\\tmulx\\t%H1, %L1, %L0\;srlx\\t%L0, 32, %H0\";
5983   else
5984     return \"sllx\\t%H1, 32, %3\\n\\tsllx\\t%H2, 32, %4\\n\\tor\\t%L1, %3, %3\\n\\tor\\t%L2, %4, %4\\n\\tmulx\\t%3, %4, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
5985 }"
5986   [(set_attr "length" "9,8")])
5987
5988 (define_insn "*cmp_mul_set"
5989   [(set (reg:CC 100)
5990         (compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5991                     (match_operand:SI 2 "arith_operand" "rI"))
5992                     (const_int 0)))
5993    (set (match_operand:SI 0 "register_operand" "=r")
5994         (mult:SI (match_dup 1) (match_dup 2)))]
5995   "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
5996   "smulcc\\t%1, %2, %0"
5997   [(set_attr "type" "imul")
5998    (set_attr "length" "1")])
5999
6000 (define_expand "mulsidi3"
6001   [(set (match_operand:DI 0 "register_operand" "")
6002         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
6003                  (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
6004   "TARGET_HARD_MUL"
6005   "
6006 {
6007   if (CONSTANT_P (operands[2]))
6008     {
6009       if (TARGET_V8PLUS)
6010         emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
6011                                               operands[2]));
6012       else
6013         emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
6014                                             operands[2]));
6015       DONE;
6016     }
6017   if (TARGET_V8PLUS)
6018     {
6019       emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
6020       DONE;
6021     }
6022 }")
6023
6024 ;; V9 puts the 64 bit product in a 64 bit register.  Only out or global
6025 ;; registers can hold 64 bit values in the V8plus environment.
6026 ;; XXX
6027 (define_insn "mulsidi3_v8plus"
6028   [(set (match_operand:DI 0 "register_operand" "=h,r")
6029         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6030                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
6031    (clobber (match_scratch:SI 3 "=X,&h"))]
6032   "TARGET_V8PLUS"
6033   "@
6034    smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
6035    smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
6036   [(set_attr "length" "2,3")])
6037
6038 ;; XXX
6039 (define_insn "const_mulsidi3_v8plus"
6040   [(set (match_operand:DI 0 "register_operand" "=h,r")
6041         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6042                  (match_operand:SI 2 "small_int" "I,I")))
6043    (clobber (match_scratch:SI 3 "=X,&h"))]
6044   "TARGET_V8PLUS"
6045   "@
6046    smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
6047    smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
6048   [(set_attr "length" "2,3")])
6049
6050 ;; XXX
6051 (define_insn "*mulsidi3_sp32"
6052   [(set (match_operand:DI 0 "register_operand" "=r")
6053         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6054                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
6055   "TARGET_HARD_MUL32"
6056   "*
6057 {
6058   return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
6059 }"
6060   [(set (attr "length")
6061         (if_then_else (eq_attr "isa" "sparclet")
6062                       (const_int 1) (const_int 2)))])
6063
6064 (define_insn "*mulsidi3_sp64"
6065   [(set (match_operand:DI 0 "register_operand" "=r")
6066         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6067                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
6068   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6069   "smul\\t%1, %2, %0"
6070   [(set_attr "length" "1")])
6071
6072 ;; Extra pattern, because sign_extend of a constant isn't valid.
6073
6074 ;; XXX
6075 (define_insn "const_mulsidi3_sp32"
6076   [(set (match_operand:DI 0 "register_operand" "=r")
6077         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6078                  (match_operand:SI 2 "small_int" "I")))]
6079   "TARGET_HARD_MUL32"
6080   "*
6081 {
6082   return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
6083 }"
6084   [(set (attr "length")
6085         (if_then_else (eq_attr "isa" "sparclet")
6086                       (const_int 1) (const_int 2)))])
6087
6088 (define_insn "const_mulsidi3_sp64"
6089   [(set (match_operand:DI 0 "register_operand" "=r")
6090         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6091                  (match_operand:SI 2 "small_int" "I")))]
6092   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6093   "smul\\t%1, %2, %0"
6094   [(set_attr "length" "1")])
6095
6096 (define_expand "smulsi3_highpart"
6097   [(set (match_operand:SI 0 "register_operand" "")
6098         (truncate:SI
6099          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
6100                                (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
6101                       (const_int 32))))]
6102   "TARGET_HARD_MUL && TARGET_ARCH32"
6103   "
6104 {
6105   if (CONSTANT_P (operands[2]))
6106     {
6107       if (TARGET_V8PLUS)
6108         {
6109           emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0],
6110                                                         operands[1],
6111                                                         operands[2],
6112                                                         GEN_INT (32)));
6113           DONE;
6114         }
6115       emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
6116       DONE;
6117     }
6118   if (TARGET_V8PLUS)
6119     {
6120       emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1],
6121                                               operands[2], GEN_INT (32)));
6122       DONE;
6123     }
6124 }")
6125
6126 ;; XXX
6127 (define_insn "smulsi3_highpart_v8plus"
6128   [(set (match_operand:SI 0 "register_operand" "=h,r")
6129         (truncate:SI
6130          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6131                                (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
6132                       (match_operand:SI 3 "const_int_operand" "i,i"))))
6133    (clobber (match_scratch:SI 4 "=X,&h"))]
6134   "TARGET_V8PLUS"
6135   "@
6136    smul %1,%2,%0\;srlx %0,%3,%0
6137    smul %1,%2,%4\;srlx %4,%3,%0"
6138   [(set_attr "length" "2")])
6139
6140 ;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
6141 ;; XXX
6142 (define_insn ""
6143   [(set (match_operand:SI 0 "register_operand" "=h,r")
6144         (subreg:SI
6145          (lshiftrt:DI
6146           (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6147                    (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
6148           (match_operand:SI 3 "const_int_operand" "i,i"))
6149          1))
6150    (clobber (match_scratch:SI 4 "=X,&h"))]
6151   "TARGET_V8PLUS"
6152   "@
6153    smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
6154    smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
6155   [(set_attr "length" "2")])
6156
6157 ;; XXX
6158 (define_insn "const_smulsi3_highpart_v8plus"
6159   [(set (match_operand:SI 0 "register_operand" "=h,r")
6160         (truncate:SI
6161          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6162                                (match_operand 2 "small_int" "i,i"))
6163                       (match_operand:SI 3 "const_int_operand" "i,i"))))
6164    (clobber (match_scratch:SI 4 "=X,&h"))]
6165   "TARGET_V8PLUS"
6166   "@
6167    smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
6168    smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
6169   [(set_attr "length" "2")])
6170
6171 ;; XXX
6172 (define_insn "*smulsi3_highpart_sp32"
6173   [(set (match_operand:SI 0 "register_operand" "=r")
6174         (truncate:SI
6175          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6176                                (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
6177                       (const_int 32))))]
6178   "TARGET_HARD_MUL32 && ! TARGET_LIVE_G0"
6179   "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
6180   [(set_attr "length" "2")])
6181
6182 ;; XXX
6183 (define_insn "const_smulsi3_highpart"
6184   [(set (match_operand:SI 0 "register_operand" "=r")
6185         (truncate:SI
6186          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
6187                                (match_operand:SI 2 "register_operand" "r"))
6188                       (const_int 32))))]
6189   "TARGET_HARD_MUL32 && ! TARGET_LIVE_G0"
6190   "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
6191   [(set_attr "length" "2")])
6192
6193 (define_expand "umulsidi3"
6194   [(set (match_operand:DI 0 "register_operand" "")
6195         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
6196                  (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
6197   "TARGET_HARD_MUL"
6198   "
6199 {
6200   if (CONSTANT_P (operands[2]))
6201     {
6202       if (TARGET_V8PLUS)
6203         emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
6204                                                operands[2]));
6205       else
6206         emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
6207                                              operands[2]));
6208       DONE;
6209     }
6210   if (TARGET_V8PLUS)
6211     {
6212       emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
6213       DONE;
6214     }
6215 }")
6216
6217 ;; XXX
6218 (define_insn "umulsidi3_v8plus"
6219   [(set (match_operand:DI 0 "register_operand" "=h,r")
6220         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6221                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
6222    (clobber (match_scratch:SI 3 "=X,&h"))]
6223   "TARGET_V8PLUS"
6224   "@
6225    umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
6226    umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
6227   [(set_attr "length" "2,3")])
6228
6229 ;; XXX
6230 (define_insn "*umulsidi3_sp32"
6231   [(set (match_operand:DI 0 "register_operand" "=r")
6232         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6233                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
6234   "TARGET_HARD_MUL32"
6235   "*
6236 {
6237   return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
6238 }"
6239   [(set (attr "length")
6240         (if_then_else (eq_attr "isa" "sparclet")
6241                       (const_int 1) (const_int 2)))])
6242
6243 (define_insn "*umulsidi3_sp64"
6244   [(set (match_operand:DI 0 "register_operand" "=r")
6245         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6246                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
6247   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6248   "umul\\t%1, %2, %0"
6249   [(set_attr "length" "1")])
6250
6251 ;; Extra pattern, because sign_extend of a constant isn't valid.
6252
6253 ;; XXX
6254 (define_insn "const_umulsidi3_sp32"
6255   [(set (match_operand:DI 0 "register_operand" "=r")
6256         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6257                  (match_operand:SI 2 "uns_small_int" "")))]
6258   "TARGET_HARD_MUL32"
6259   "*
6260 {
6261   return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
6262 }"
6263   [(set (attr "length")
6264         (if_then_else (eq_attr "isa" "sparclet")
6265                       (const_int 1) (const_int 2)))])
6266
6267 (define_insn "const_umulsidi3_sp64"
6268   [(set (match_operand:DI 0 "register_operand" "=r")
6269         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6270                  (match_operand:SI 2 "uns_small_int" "")))]
6271   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6272   "umul\\t%1, %2, %0"
6273   [(set_attr "length" "1")])
6274
6275 ;; XXX
6276 (define_insn "const_umulsidi3_v8plus"
6277   [(set (match_operand:DI 0 "register_operand" "=h,r")
6278         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6279                  (match_operand:SI 2 "uns_small_int" "")))
6280    (clobber (match_scratch:SI 3 "=X,h"))]
6281   "TARGET_V8PLUS"
6282   "@
6283    umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
6284    umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
6285   [(set_attr "length" "2,3")])
6286
6287 (define_expand "umulsi3_highpart"
6288   [(set (match_operand:SI 0 "register_operand" "")
6289         (truncate:SI
6290          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
6291                                (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
6292                       (const_int 32))))]
6293   "TARGET_HARD_MUL && TARGET_ARCH32"
6294   "
6295 {
6296   if (CONSTANT_P (operands[2]))
6297     {
6298       if (TARGET_V8PLUS)
6299         {
6300           emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0],
6301                                                         operands[1],
6302                                                         operands[2],
6303                                                         GEN_INT (32)));
6304           DONE;
6305         }
6306       emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
6307       DONE;
6308     }
6309   if (TARGET_V8PLUS)
6310     {
6311       emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1],
6312                                               operands[2], GEN_INT (32)));
6313       DONE;
6314     }
6315 }")
6316
6317 ;; XXX
6318 (define_insn "umulsi3_highpart_v8plus"
6319   [(set (match_operand:SI 0 "register_operand" "=h,r")
6320         (truncate:SI
6321          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6322                                (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
6323                       (match_operand:SI 3 "const_int_operand" "i,i"))))
6324    (clobber (match_scratch:SI 4 "=X,h"))]
6325   "TARGET_V8PLUS"
6326   "@
6327    umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
6328    umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
6329   [(set_attr "length" "2")])
6330
6331 ;; XXX
6332 (define_insn "const_umulsi3_highpart_v8plus"
6333   [(set (match_operand:SI 0 "register_operand" "=h,r")
6334         (truncate:SI
6335          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
6336                                (match_operand:SI 2 "uns_small_int" ""))
6337                       (match_operand:SI 3 "const_int_operand" "i,i"))))
6338    (clobber (match_scratch:SI 4 "=X,h"))]
6339   "TARGET_V8PLUS"
6340   "@
6341    umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
6342    umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
6343   [(set_attr "length" "2")])
6344
6345 ;; XXX
6346 (define_insn "*umulsi3_highpart_sp32"
6347   [(set (match_operand:SI 0 "register_operand" "=r")
6348         (truncate:SI
6349          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6350                                (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
6351                       (const_int 32))))]
6352   "TARGET_HARD_MUL32 && ! TARGET_LIVE_G0"
6353   "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
6354   [(set_attr "length" "2")])
6355
6356 ;; XXX
6357 (define_insn "const_umulsi3_highpart"
6358   [(set (match_operand:SI 0 "register_operand" "=r")
6359         (truncate:SI
6360          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
6361                                (match_operand:SI 2 "uns_small_int" ""))
6362                       (const_int 32))))]
6363   "TARGET_HARD_MUL32 && ! TARGET_LIVE_G0"
6364   "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
6365   [(set_attr "length" "2")])
6366
6367 ;; The v8 architecture specifies that there must be 3 instructions between
6368 ;; a y register write and a use of it for correct results.
6369
6370 (define_expand "divsi3"
6371   [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
6372                    (div:SI (match_operand:SI 1 "register_operand" "r,r")
6373                            (match_operand:SI 2 "input_operand" "rI,m")))
6374               (clobber (match_scratch:SI 3 "=&r,&r"))])]
6375   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
6376   "
6377 {
6378   if (TARGET_ARCH64)
6379     {
6380       operands[3] = gen_reg_rtx(SImode);
6381       emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
6382       emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
6383                                   operands[3]));
6384       DONE;
6385     }
6386 }")
6387
6388 (define_insn "divsi3_sp32"
6389   [(set (match_operand:SI 0 "register_operand" "=r,r")
6390         (div:SI (match_operand:SI 1 "register_operand" "r,r")
6391                 (match_operand:SI 2 "input_operand" "rI,m")))
6392    (clobber (match_scratch:SI 3 "=&r,&r"))]
6393   "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
6394    && TARGET_ARCH32"
6395   "*
6396 {
6397   if (which_alternative == 0)
6398     if (TARGET_V9)
6399       return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdiv\\t%1, %2, %0\";
6400     else
6401       return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
6402   else
6403     if (TARGET_V9)
6404       return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
6405     else
6406       return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
6407 }"
6408   [(set (attr "length")
6409         (if_then_else (eq_attr "isa" "v9")
6410                       (const_int 4) (const_int 7)))])
6411
6412 (define_insn "divsi3_sp64"
6413   [(set (match_operand:SI 0 "register_operand" "=r")
6414         (div:SI (match_operand:SI 1 "register_operand" "r")
6415                 (match_operand:SI 2 "input_operand" "rI")))
6416    (use (match_operand:SI 3 "register_operand" "r"))]
6417   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6418   "wr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0"
6419   [(set_attr "length" "2")])
6420
6421 (define_insn "divdi3"
6422   [(set (match_operand:DI 0 "register_operand" "=r")
6423         (div:DI (match_operand:DI 1 "register_operand" "r")
6424                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
6425   "TARGET_ARCH64"
6426   "sdivx\\t%1, %2, %0")
6427
6428 (define_insn "*cmp_sdiv_cc_set"
6429   [(set (reg:CC 100)
6430         (compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
6431                             (match_operand:SI 2 "arith_operand" "rI"))
6432                     (const_int 0)))
6433    (set (match_operand:SI 0 "register_operand" "=r")
6434         (div:SI (match_dup 1) (match_dup 2)))
6435    (clobber (match_scratch:SI 3 "=&r"))]
6436   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
6437   "*
6438 {
6439   if (TARGET_V9)
6440     return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdivcc\\t%1, %2, %0\";
6441   else
6442     return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
6443 }"
6444   [(set (attr "length")
6445         (if_then_else (eq_attr "isa" "v9")
6446                       (const_int 3) (const_int 6)))])
6447
6448 ;; XXX
6449 (define_expand "udivsi3"
6450   [(set (match_operand:SI 0 "register_operand" "")
6451         (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
6452                  (match_operand:SI 2 "input_operand" "")))]
6453   "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && ! TARGET_LIVE_G0"
6454   "")
6455
6456 (define_insn "udivsi3_sp32"
6457   [(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
6458         (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
6459                  (match_operand:SI 2 "input_operand" "rI,m,r")))]
6460   "(TARGET_V8
6461     || TARGET_DEPRECATED_V8_INSNS)
6462    && TARGET_ARCH32 && ! TARGET_LIVE_G0"
6463   "*
6464 {
6465   output_asm_insn (\"wr\\t%%g0, %%g0, %%y\", operands);
6466   switch (which_alternative)
6467     {
6468     default:
6469       return \"nop\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %2, %0\";
6470     case 1:
6471       return \"ld\\t%2, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %0, %0\";
6472     case 2:
6473       return \"ld\\t%1, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%0, %2, %0\";
6474     }
6475 }"
6476   [(set_attr "length" "5")])
6477
6478 (define_insn "udivsi3_sp64"
6479   [(set (match_operand:SI 0 "register_operand" "=r")
6480         (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
6481                  (match_operand:SI 2 "input_operand" "rI")))]
6482   "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
6483   "wr\\t%%g0, 0, %%y\\n\\tudiv\\t%1, %2, %0"
6484   [(set_attr "length" "2")])
6485
6486 (define_insn "udivdi3"
6487   [(set (match_operand:DI 0 "register_operand" "=r")
6488         (udiv:DI (match_operand:DI 1 "register_operand" "r")
6489                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
6490   "TARGET_ARCH64"
6491   "udivx\\t%1, %2, %0")
6492
6493 (define_insn "*cmp_udiv_cc_set"
6494   [(set (reg:CC 100)
6495         (compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
6496                              (match_operand:SI 2 "arith_operand" "rI"))
6497                     (const_int 0)))
6498    (set (match_operand:SI 0 "register_operand" "=r")
6499         (udiv:SI (match_dup 1) (match_dup 2)))]
6500   "(TARGET_V8
6501     || TARGET_DEPRECATED_V8_INSNS)
6502    && ! TARGET_LIVE_G0"
6503   "*
6504 {
6505   if (TARGET_V9)
6506     return \"wr\\t%%g0, %%g0, %%y\\n\\tudivcc\\t%1, %2, %0\";
6507   else
6508     return \"wr\\t%%g0, %%g0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tudivcc\\t%1, %2, %0\";
6509 }"
6510   [(set (attr "length")
6511         (if_then_else (eq_attr "isa" "v9")
6512                       (const_int 2) (const_int 5)))])
6513
6514 ; sparclet multiply/accumulate insns
6515
6516 (define_insn "*smacsi"
6517   [(set (match_operand:SI 0 "register_operand" "=r")
6518         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
6519                           (match_operand:SI 2 "arith_operand" "rI"))
6520                  (match_operand:SI 3 "register_operand" "0")))]
6521   "TARGET_SPARCLET"
6522   "smac\\t%1, %2, %0"
6523   [(set_attr "type" "imul")
6524    (set_attr "length" "1")])
6525
6526 (define_insn "*smacdi"
6527   [(set (match_operand:DI 0 "register_operand" "=r")
6528         (plus:DI (mult:DI (sign_extend:DI
6529                            (match_operand:SI 1 "register_operand" "%r"))
6530                           (sign_extend:DI
6531                            (match_operand:SI 2 "register_operand" "r")))
6532                  (match_operand:DI 3 "register_operand" "0")))]
6533   "TARGET_SPARCLET"
6534   "smacd\\t%1, %2, %L0"
6535   [(set_attr "type" "imul")
6536    (set_attr "length" "1")])
6537
6538 (define_insn "*umacdi"
6539   [(set (match_operand:DI 0 "register_operand" "=r")
6540         (plus:DI (mult:DI (zero_extend:DI
6541                            (match_operand:SI 1 "register_operand" "%r"))
6542                           (zero_extend:DI
6543                            (match_operand:SI 2 "register_operand" "r")))
6544                  (match_operand:DI 3 "register_operand" "0")))]
6545   "TARGET_SPARCLET"
6546   "umacd\\t%1, %2, %L0"
6547   [(set_attr "type" "imul")
6548    (set_attr "length" "1")])
6549 \f
6550 ;;- Boolean instructions
6551 ;; We define DImode `and' so with DImode `not' we can get
6552 ;; DImode `andn'.  Other combinations are possible.
6553
6554 (define_expand "anddi3"
6555   [(set (match_operand:DI 0 "register_operand" "")
6556         (and:DI (match_operand:DI 1 "arith_double_operand" "")
6557                 (match_operand:DI 2 "arith_double_operand" "")))]
6558   ""
6559   "")
6560
6561 (define_insn "*anddi3_sp32"
6562   [(set (match_operand:DI 0 "register_operand" "=r,b")
6563         (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6564                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6565   "! TARGET_ARCH64"
6566   "@
6567   #
6568   fand\\t%1, %2, %0"
6569   [(set_attr "type" "ialu,fp")
6570    (set_attr "length" "2,1")])
6571
6572 (define_insn "*anddi3_sp64"
6573   [(set (match_operand:DI 0 "register_operand" "=r,b")
6574         (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6575                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6576   "TARGET_ARCH64"
6577   "@
6578    and\\t%1, %2, %0
6579    fand\\t%1, %2, %0"
6580   [(set_attr "type" "ialu,fp")
6581    (set_attr "length" "1,1")])
6582
6583 (define_insn "andsi3"
6584   [(set (match_operand:SI 0 "register_operand" "=r,d")
6585         (and:SI (match_operand:SI 1 "arith_operand" "%r,d")
6586                 (match_operand:SI 2 "arith_operand" "rI,d")))]
6587   ""
6588   "@
6589    and\\t%1, %2, %0
6590    fands\\t%1, %2, %0"
6591   [(set_attr "type" "ialu,fp")
6592    (set_attr "length" "1,1")])
6593
6594 (define_split
6595   [(set (match_operand:SI 0 "register_operand" "")
6596         (and:SI (match_operand:SI 1 "register_operand" "")
6597                 (match_operand:SI 2 "" "")))
6598    (clobber (match_operand:SI 3 "register_operand" ""))]
6599   "GET_CODE (operands[2]) == CONST_INT
6600    && !SMALL_INT32 (operands[2])
6601    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6602   [(set (match_dup 3) (match_dup 4))
6603    (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
6604   "
6605 {
6606   operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
6607 }")
6608
6609 ;; Split DImode logical operations requiring two instructions.
6610 (define_split
6611   [(set (match_operand:DI 0 "register_operand" "")
6612         (match_operator:DI 1 "cc_arithop"       ; AND, IOR, XOR
6613                            [(match_operand:DI 2 "register_operand" "")
6614                             (match_operand:DI 3 "arith_double_operand" "")]))]
6615   "! TARGET_ARCH64
6616    && reload_completed
6617    && ((GET_CODE (operands[0]) == REG
6618         && REGNO (operands[0]) < 32)
6619        || (GET_CODE (operands[0]) == SUBREG
6620            && GET_CODE (SUBREG_REG (operands[0])) == REG
6621            && REGNO (SUBREG_REG (operands[0])) < 32))"
6622   [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
6623    (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
6624   "
6625 {
6626   if (GET_CODE (operands[0]) == SUBREG)
6627     operands[0] = alter_subreg (operands[0]);
6628   operands[4] = gen_highpart (SImode, operands[0]);
6629   operands[5] = gen_lowpart (SImode, operands[0]);
6630   operands[6] = gen_highpart (SImode, operands[2]);
6631   operands[7] = gen_lowpart (SImode, operands[2]);
6632   if (GET_CODE (operands[3]) == CONST_INT)
6633     {
6634       if (INTVAL (operands[3]) < 0)
6635         operands[8] = constm1_rtx;
6636       else
6637         operands[8] = const0_rtx;
6638     }
6639   else
6640     operands[8] = gen_highpart (SImode, operands[3]);
6641   operands[9] = gen_lowpart (SImode, operands[3]);
6642 }")
6643
6644 (define_insn "*and_not_di_sp32"
6645   [(set (match_operand:DI 0 "register_operand" "=r,b")
6646         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6647                 (match_operand:DI 2 "register_operand" "r,b")))]
6648   "! TARGET_ARCH64"
6649   "@
6650    #
6651    fandnot1\\t%1, %2, %0"
6652   [(set_attr "type" "ialu,fp")
6653    (set_attr "length" "2,1")])
6654
6655 (define_split
6656   [(set (match_operand:DI 0 "register_operand" "")
6657         (and:DI (not:DI (match_operand:DI 1 "register_operand" ""))
6658                 (match_operand:DI 2 "register_operand" "")))]
6659   "! TARGET_ARCH64
6660    && reload_completed
6661    && ((GET_CODE (operands[0]) == REG
6662         && REGNO (operands[0]) < 32)
6663        || (GET_CODE (operands[0]) == SUBREG
6664            && GET_CODE (SUBREG_REG (operands[0])) == REG
6665            && REGNO (SUBREG_REG (operands[0])) < 32))"
6666   [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
6667    (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
6668   "if (GET_CODE (operands[0]) == SUBREG)
6669      operands[0] = alter_subreg (operands[0]);
6670    operands[3] = gen_highpart (SImode, operands[0]);
6671    operands[4] = gen_highpart (SImode, operands[1]);
6672    operands[5] = gen_highpart (SImode, operands[2]);
6673    operands[6] = gen_lowpart (SImode, operands[0]);
6674    operands[7] = gen_lowpart (SImode, operands[1]);
6675    operands[8] = gen_lowpart (SImode, operands[2]);")
6676
6677 (define_insn "*and_not_di_sp64"
6678   [(set (match_operand:DI 0 "register_operand" "=r,b")
6679         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6680                 (match_operand:DI 2 "register_operand" "r,b")))]
6681   "TARGET_ARCH64"
6682   "@
6683    andn\\t%2, %1, %0
6684    fandnot1\\t%1, %2, %0"
6685   [(set_attr "type" "ialu,fp")
6686    (set_attr "length" "1,1")])
6687
6688 (define_insn "*and_not_si"
6689   [(set (match_operand:SI 0 "register_operand" "=r,d")
6690         (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
6691                 (match_operand:SI 2 "register_operand" "r,d")))]
6692   ""
6693   "@
6694    andn\\t%2, %1, %0
6695    fandnot1s\\t%1, %2, %0"
6696   [(set_attr "type" "ialu,fp")
6697    (set_attr "length" "1,1")])
6698
6699 (define_expand "iordi3"
6700   [(set (match_operand:DI 0 "register_operand" "")
6701         (ior:DI (match_operand:DI 1 "arith_double_operand" "")
6702                 (match_operand:DI 2 "arith_double_operand" "")))]
6703   ""
6704   "")
6705
6706 (define_insn "*iordi3_sp32"
6707   [(set (match_operand:DI 0 "register_operand" "=r,b")
6708         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6709                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6710   "! TARGET_ARCH64"
6711   "@
6712   #
6713   for\\t%1, %2, %0"
6714   [(set_attr "type" "ialu,fp")
6715    (set_attr "length" "2,1")])
6716
6717 (define_insn "*iordi3_sp64"
6718   [(set (match_operand:DI 0 "register_operand" "=r,b")
6719         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6720                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6721   "TARGET_ARCH64"
6722   "@
6723   or\\t%1, %2, %0
6724   for\\t%1, %2, %0"
6725   [(set_attr "type" "ialu,fp")
6726    (set_attr "length" "1,1")])
6727
6728 (define_insn "iorsi3"
6729   [(set (match_operand:SI 0 "register_operand" "=r,d")
6730         (ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
6731                 (match_operand:SI 2 "arith_operand" "rI,d")))]
6732   ""
6733   "@
6734    or\\t%1, %2, %0
6735    fors\\t%1, %2, %0"
6736   [(set_attr "type" "ialu,fp")
6737    (set_attr "length" "1,1")])
6738
6739 (define_split
6740   [(set (match_operand:SI 0 "register_operand" "")
6741         (ior:SI (match_operand:SI 1 "register_operand" "")
6742                 (match_operand:SI 2 "" "")))
6743    (clobber (match_operand:SI 3 "register_operand" ""))]
6744   "GET_CODE (operands[2]) == CONST_INT
6745    && !SMALL_INT32 (operands[2])
6746    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6747   [(set (match_dup 3) (match_dup 4))
6748    (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
6749   "
6750 {
6751   operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
6752 }")
6753
6754 (define_insn "*or_not_di_sp32"
6755   [(set (match_operand:DI 0 "register_operand" "=r,b")
6756         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6757                 (match_operand:DI 2 "register_operand" "r,b")))]
6758   "! TARGET_ARCH64"
6759   "@
6760    #
6761    fornot1\\t%1, %2, %0"
6762   [(set_attr "type" "ialu,fp")
6763    (set_attr "length" "2,1")])
6764
6765 (define_split
6766   [(set (match_operand:DI 0 "register_operand" "")
6767         (ior:DI (not:DI (match_operand:DI 1 "register_operand" ""))
6768                 (match_operand:DI 2 "register_operand" "")))]
6769   "! TARGET_ARCH64
6770    && reload_completed
6771    && ((GET_CODE (operands[0]) == REG
6772         && REGNO (operands[0]) < 32)
6773        || (GET_CODE (operands[0]) == SUBREG
6774            && GET_CODE (SUBREG_REG (operands[0])) == REG
6775            && REGNO (SUBREG_REG (operands[0])) < 32))"
6776   [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
6777    (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
6778   "if (GET_CODE (operands[0]) == SUBREG)
6779      operands[0] = alter_subreg (operands[0]);
6780    operands[3] = gen_highpart (SImode, operands[0]);
6781    operands[4] = gen_highpart (SImode, operands[1]);
6782    operands[5] = gen_highpart (SImode, operands[2]);
6783    operands[6] = gen_lowpart (SImode, operands[0]);
6784    operands[7] = gen_lowpart (SImode, operands[1]);
6785    operands[8] = gen_lowpart (SImode, operands[2]);")
6786
6787 (define_insn "*or_not_di_sp64"
6788   [(set (match_operand:DI 0 "register_operand" "=r,b")
6789         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6790                 (match_operand:DI 2 "register_operand" "r,b")))]
6791   "TARGET_ARCH64"
6792   "@
6793   orn\\t%2, %1, %0
6794   fornot1\\t%1, %2, %0"
6795   [(set_attr "type" "ialu,fp")
6796    (set_attr "length" "1,1")])
6797
6798 (define_insn "*or_not_si"
6799   [(set (match_operand:SI 0 "register_operand" "=r,d")
6800         (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
6801                 (match_operand:SI 2 "register_operand" "r,d")))]
6802   ""
6803   "@
6804    orn\\t%2, %1, %0
6805    fornot1s\\t%1, %2, %0"
6806   [(set_attr "type" "ialu,fp")
6807    (set_attr "length" "1,1")])
6808
6809 (define_expand "xordi3"
6810   [(set (match_operand:DI 0 "register_operand" "")
6811         (xor:DI (match_operand:DI 1 "arith_double_operand" "")
6812                 (match_operand:DI 2 "arith_double_operand" "")))]
6813   ""
6814   "")
6815
6816 (define_insn "*xordi3_sp32"
6817   [(set (match_operand:DI 0 "register_operand" "=r,b")
6818         (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6819                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6820   "! TARGET_ARCH64"
6821   "@
6822   #
6823   fxor\\t%1, %2, %0"
6824   [(set_attr "length" "2,1")
6825    (set_attr "type" "ialu,fp")])
6826
6827 (define_insn "*xordi3_sp64"
6828   [(set (match_operand:DI 0 "register_operand" "=r,b")
6829         (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
6830                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6831   "TARGET_ARCH64"
6832   "@
6833   xor\\t%r1, %2, %0
6834   fxor\\t%1, %2, %0"
6835   [(set_attr "type" "ialu,fp")
6836    (set_attr "length" "1,1")])
6837
6838 (define_insn "*xordi3_sp64_dbl"
6839   [(set (match_operand:DI 0 "register_operand" "=r")
6840         (xor:DI (match_operand:DI 1 "register_operand" "r")
6841                 (match_operand:DI 2 "const64_operand" "")))]
6842   "(TARGET_ARCH64
6843     && HOST_BITS_PER_WIDE_INT != 64)"
6844   "xor\\t%1, %2, %0"
6845   [(set_attr "type" "ialu")
6846    (set_attr "length" "1")])
6847
6848 (define_insn "xorsi3"
6849   [(set (match_operand:SI 0 "register_operand" "=r,d")
6850         (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
6851                 (match_operand:SI 2 "arith_operand" "rI,d")))]
6852   ""
6853   "@
6854    xor\\t%r1, %2, %0
6855    fxors\\t%1, %2, %0"
6856   [(set_attr "type" "ialu,fp")
6857    (set_attr "length" "1,1")])
6858
6859 (define_split
6860   [(set (match_operand:SI 0 "register_operand" "")
6861         (xor:SI (match_operand:SI 1 "register_operand" "")
6862                 (match_operand:SI 2 "" "")))
6863    (clobber (match_operand:SI 3 "register_operand" ""))]
6864   "GET_CODE (operands[2]) == CONST_INT
6865    && !SMALL_INT32 (operands[2])
6866    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6867   [(set (match_dup 3) (match_dup 4))
6868    (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
6869   "
6870 {
6871   operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
6872 }")
6873
6874 (define_split
6875   [(set (match_operand:SI 0 "register_operand" "")
6876         (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
6877                         (match_operand:SI 2 "" ""))))
6878    (clobber (match_operand:SI 3 "register_operand" ""))]
6879   "GET_CODE (operands[2]) == CONST_INT
6880    && !SMALL_INT32 (operands[2])
6881    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6882   [(set (match_dup 3) (match_dup 4))
6883    (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
6884   "
6885 {
6886   operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
6887 }")
6888
6889 ;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
6890 ;; Combine now canonicalizes to the rightmost expression.
6891 (define_insn "*xor_not_di_sp32"
6892   [(set (match_operand:DI 0 "register_operand" "=r,b")
6893         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
6894                         (match_operand:DI 2 "register_operand" "r,b"))))]
6895   "! TARGET_ARCH64"
6896   "@
6897    #
6898    fxnor\\t%1, %2, %0"
6899   [(set_attr "length" "2,1")
6900    (set_attr "type" "ialu,fp")])
6901
6902 (define_split
6903   [(set (match_operand:DI 0 "register_operand" "")
6904         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "")
6905                         (match_operand:DI 2 "register_operand" ""))))]
6906   "! TARGET_ARCH64
6907    && reload_completed
6908    && ((GET_CODE (operands[0]) == REG
6909         && REGNO (operands[0]) < 32)
6910        || (GET_CODE (operands[0]) == SUBREG
6911            && GET_CODE (SUBREG_REG (operands[0])) == REG
6912            && REGNO (SUBREG_REG (operands[0])) < 32))"
6913   [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
6914    (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
6915   "if (GET_CODE (operands[0]) == SUBREG)
6916      operands[0] = alter_subreg (operands[0]);
6917    operands[3] = gen_highpart (SImode, operands[0]);
6918    operands[4] = gen_highpart (SImode, operands[1]);
6919    operands[5] = gen_highpart (SImode, operands[2]);
6920    operands[6] = gen_lowpart (SImode, operands[0]);
6921    operands[7] = gen_lowpart (SImode, operands[1]);
6922    operands[8] = gen_lowpart (SImode, operands[2]);")
6923
6924 (define_insn "*xor_not_di_sp64"
6925   [(set (match_operand:DI 0 "register_operand" "=r,b")
6926         (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
6927                         (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
6928   "TARGET_ARCH64"
6929   "@
6930   xnor\\t%r1, %2, %0
6931   fxnor\\t%1, %2, %0"
6932   [(set_attr "type" "ialu,fp")
6933    (set_attr "length" "1,1")])
6934
6935 (define_insn "*xor_not_si"
6936   [(set (match_operand:SI 0 "register_operand" "=r,d")
6937         (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
6938                         (match_operand:SI 2 "arith_operand" "rI,d"))))]
6939   ""
6940   "@
6941    xnor\\t%r1, %2, %0
6942    fxnors\\t%1, %2, %0"
6943   [(set_attr "type" "ialu,fp")
6944    (set_attr "length" "1,1")])
6945
6946 ;; These correspond to the above in the case where we also (or only)
6947 ;; want to set the condition code.  
6948
6949 (define_insn "*cmp_cc_arith_op"
6950   [(set (reg:CC 100)
6951         (compare:CC
6952          (match_operator:SI 2 "cc_arithop"
6953                             [(match_operand:SI 0 "arith_operand" "%r")
6954                              (match_operand:SI 1 "arith_operand" "rI")])
6955          (const_int 0)))]
6956   "! TARGET_LIVE_G0"
6957   "%A2cc\\t%0, %1, %%g0"
6958   [(set_attr "type" "compare")
6959    (set_attr "length" "1")])
6960
6961 (define_insn "*cmp_ccx_arith_op"
6962   [(set (reg:CCX 100)
6963         (compare:CCX
6964          (match_operator:DI 2 "cc_arithop"
6965                             [(match_operand:DI 0 "arith_double_operand" "%r")
6966                              (match_operand:DI 1 "arith_double_operand" "rHI")])
6967          (const_int 0)))]
6968   "TARGET_ARCH64"
6969   "%A2cc\\t%0, %1, %%g0"
6970   [(set_attr "type" "compare")
6971    (set_attr "length" "1")])
6972
6973 (define_insn "*cmp_cc_arith_op_set"
6974   [(set (reg:CC 100)
6975         (compare:CC
6976          (match_operator:SI 3 "cc_arithop"
6977                             [(match_operand:SI 1 "arith_operand" "%r")
6978                              (match_operand:SI 2 "arith_operand" "rI")])
6979          (const_int 0)))
6980    (set (match_operand:SI 0 "register_operand" "=r")
6981         (match_dup 3))]
6982   ""
6983   "%A3cc\\t%1, %2, %0"
6984   [(set_attr "type" "compare")
6985    (set_attr "length" "1")])
6986
6987 (define_insn "*cmp_ccx_arith_op_set"
6988   [(set (reg:CCX 100)
6989         (compare:CCX
6990          (match_operator:DI 3 "cc_arithop"
6991                             [(match_operand:DI 1 "arith_double_operand" "%r")
6992                              (match_operand:DI 2 "arith_double_operand" "rHI")])
6993          (const_int 0)))
6994    (set (match_operand:DI 0 "register_operand" "=r")
6995         (match_dup 3))]
6996   "TARGET_ARCH64"
6997   "%A3cc\\t%1, %2, %0"
6998   [(set_attr "type" "compare")
6999    (set_attr "length" "1")])
7000
7001 (define_insn "*cmp_cc_xor_not"
7002   [(set (reg:CC 100)
7003         (compare:CC
7004          (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
7005                          (match_operand:SI 1 "arith_operand" "rI")))
7006          (const_int 0)))]
7007   "! TARGET_LIVE_G0"
7008   "xnorcc\\t%r0, %1, %%g0"
7009   [(set_attr "type" "compare")
7010    (set_attr "length" "1")])
7011
7012 (define_insn "*cmp_ccx_xor_not"
7013   [(set (reg:CCX 100)
7014         (compare:CCX
7015          (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
7016                          (match_operand:DI 1 "arith_double_operand" "rHI")))
7017          (const_int 0)))]
7018   "TARGET_ARCH64"
7019   "xnorcc\\t%r0, %1, %%g0"
7020   [(set_attr "type" "compare")
7021    (set_attr "length" "1")])
7022
7023 (define_insn "*cmp_cc_xor_not_set"
7024   [(set (reg:CC 100)
7025         (compare:CC
7026          (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
7027                          (match_operand:SI 2 "arith_operand" "rI")))
7028          (const_int 0)))
7029    (set (match_operand:SI 0 "register_operand" "=r")
7030         (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
7031   ""
7032   "xnorcc\\t%r1, %2, %0"
7033   [(set_attr "type" "compare")
7034    (set_attr "length" "1")])
7035
7036 (define_insn "*cmp_ccx_xor_not_set"
7037   [(set (reg:CCX 100)
7038         (compare:CCX
7039          (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
7040                          (match_operand:DI 2 "arith_double_operand" "rHI")))
7041          (const_int 0)))
7042    (set (match_operand:DI 0 "register_operand" "=r")
7043         (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
7044   "TARGET_ARCH64"
7045   "xnorcc\\t%r1, %2, %0"
7046   [(set_attr "type" "compare")
7047    (set_attr "length" "1")])
7048
7049 (define_insn "*cmp_cc_arith_op_not"
7050   [(set (reg:CC 100)
7051         (compare:CC
7052          (match_operator:SI 2 "cc_arithopn"
7053                             [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
7054                              (match_operand:SI 1 "reg_or_0_operand" "rJ")])
7055          (const_int 0)))]
7056   "! TARGET_LIVE_G0"
7057   "%B2cc\\t%r1, %0, %%g0"
7058   [(set_attr "type" "compare")
7059    (set_attr "length" "1")])
7060
7061 (define_insn "*cmp_ccx_arith_op_not"
7062   [(set (reg:CCX 100)
7063         (compare:CCX
7064          (match_operator:DI 2 "cc_arithopn"
7065                             [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
7066                              (match_operand:DI 1 "reg_or_0_operand" "rJ")])
7067          (const_int 0)))]
7068   "TARGET_ARCH64"
7069   "%B2cc\\t%r1, %0, %%g0"
7070   [(set_attr "type" "compare")
7071    (set_attr "length" "1")])
7072
7073 (define_insn "*cmp_cc_arith_op_not_set"
7074   [(set (reg:CC 100)
7075         (compare:CC
7076          (match_operator:SI 3 "cc_arithopn"
7077                             [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
7078                              (match_operand:SI 2 "reg_or_0_operand" "rJ")])
7079          (const_int 0)))
7080    (set (match_operand:SI 0 "register_operand" "=r")
7081         (match_dup 3))]
7082   ""
7083   "%B3cc\\t%r2, %1, %0"
7084   [(set_attr "type" "compare")
7085    (set_attr "length" "1")])
7086
7087 (define_insn "*cmp_ccx_arith_op_not_set"
7088   [(set (reg:CCX 100)
7089         (compare:CCX
7090          (match_operator:DI 3 "cc_arithopn"
7091                             [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
7092                              (match_operand:DI 2 "reg_or_0_operand" "rJ")])
7093          (const_int 0)))
7094    (set (match_operand:DI 0 "register_operand" "=r")
7095         (match_dup 3))]
7096   "TARGET_ARCH64"
7097   "%B3cc\\t%r2, %1, %0"
7098   [(set_attr "type" "compare")
7099    (set_attr "length" "1")])
7100
7101 ;; We cannot use the "neg" pseudo insn because the Sun assembler
7102 ;; does not know how to make it work for constants.
7103
7104 (define_expand "negdi2"
7105   [(set (match_operand:DI 0 "register_operand" "=r")
7106         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
7107   ""
7108   "
7109 {
7110   if (! TARGET_ARCH64)
7111     {
7112       emit_insn (gen_rtx_PARALLEL
7113                  (VOIDmode,
7114                   gen_rtvec (2,
7115                              gen_rtx_SET (VOIDmode, operand0,
7116                                           gen_rtx_NEG (DImode, operand1)),
7117                              gen_rtx_CLOBBER (VOIDmode,
7118                                               gen_rtx_REG (CCmode,
7119                                                            SPARC_ICC_REG)))));
7120       DONE;
7121     }
7122 }")
7123
7124 (define_insn "*negdi2_sp32"
7125   [(set (match_operand:DI 0 "register_operand" "=r")
7126         (neg:DI (match_operand:DI 1 "register_operand" "r")))
7127    (clobber (reg:CC 100))]
7128   "! TARGET_ARCH64
7129    && ! TARGET_LIVE_G0"
7130   "#"
7131   [(set_attr "type" "unary")
7132    (set_attr "length" "2")])
7133
7134 (define_split
7135   [(set (match_operand:DI 0 "register_operand" "")
7136         (neg:DI (match_operand:DI 1 "register_operand" "")))
7137    (clobber (reg:CC 100))]
7138   "! TARGET_ARCH64
7139    && ! TARGET_LIVE_G0
7140    && reload_completed"
7141   [(parallel [(set (reg:CC_NOOV 100)
7142                    (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
7143                                     (const_int 0)))
7144               (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
7145    (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
7146                                 (ltu:SI (reg:CC 100) (const_int 0))))]
7147   "operands[2] = gen_highpart (SImode, operands[0]);
7148    operands[3] = gen_highpart (SImode, operands[1]);
7149    operands[4] = gen_lowpart (SImode, operands[0]);
7150    operands[5] = gen_lowpart (SImode, operands[1]);")
7151
7152 (define_insn "*negdi2_sp64"
7153   [(set (match_operand:DI 0 "register_operand" "=r")
7154         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
7155   "TARGET_ARCH64"
7156   "sub\\t%%g0, %1, %0"
7157   [(set_attr "type" "unary")
7158    (set_attr "length" "1")])
7159
7160 (define_expand "negsi2"
7161   [(set (match_operand:SI 0 "register_operand" "")
7162         (neg:SI (match_operand:SI 1 "arith_operand" "")))]
7163   ""
7164   "
7165 {
7166   if (TARGET_LIVE_G0)
7167     {
7168       rtx zero_reg = gen_reg_rtx (SImode);
7169
7170       emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
7171       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
7172                                       gen_rtx_MINUS (SImode, zero_reg,
7173                                                              operands[1])));
7174       DONE;
7175     }
7176 }")
7177
7178 (define_insn "*negsi2_not_liveg0"
7179   [(set (match_operand:SI 0 "register_operand" "=r")
7180         (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
7181   "! TARGET_LIVE_G0"
7182   "sub\\t%%g0, %1, %0"
7183   [(set_attr "type" "unary")
7184    (set_attr "length" "1")])
7185
7186 (define_insn "*cmp_cc_neg"
7187   [(set (reg:CC_NOOV 100)
7188         (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
7189                          (const_int 0)))]
7190   "! TARGET_LIVE_G0"
7191   "subcc\\t%%g0, %0, %%g0"
7192   [(set_attr "type" "compare")
7193    (set_attr "length" "1")])
7194
7195 (define_insn "*cmp_ccx_neg"
7196   [(set (reg:CCX_NOOV 100)
7197         (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
7198                           (const_int 0)))]
7199   "TARGET_ARCH64"
7200   "subcc\\t%%g0, %0, %%g0"
7201   [(set_attr "type" "compare")
7202    (set_attr "length" "1")])
7203
7204 (define_insn "*cmp_cc_set_neg"
7205   [(set (reg:CC_NOOV 100)
7206         (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
7207                          (const_int 0)))
7208    (set (match_operand:SI 0 "register_operand" "=r")
7209         (neg:SI (match_dup 1)))]
7210   "! TARGET_LIVE_G0"
7211   "subcc\\t%%g0, %1, %0"
7212   [(set_attr "type" "compare")
7213    (set_attr "length" "1")])
7214
7215 (define_insn "*cmp_ccx_set_neg"
7216   [(set (reg:CCX_NOOV 100)
7217         (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
7218                           (const_int 0)))
7219    (set (match_operand:DI 0 "register_operand" "=r")
7220         (neg:DI (match_dup 1)))]
7221   "TARGET_ARCH64"
7222   "subcc\\t%%g0, %1, %0"
7223   [(set_attr "type" "compare")
7224    (set_attr "length" "1")])
7225
7226 ;; We cannot use the "not" pseudo insn because the Sun assembler
7227 ;; does not know how to make it work for constants.
7228 (define_expand "one_cmpldi2"
7229   [(set (match_operand:DI 0 "register_operand" "")
7230         (not:DI (match_operand:DI 1 "register_operand" "")))]
7231   ""
7232   "")
7233
7234 (define_insn "*one_cmpldi2_sp32"
7235   [(set (match_operand:DI 0 "register_operand" "=r,b")
7236         (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
7237   "! TARGET_ARCH64"
7238   "@
7239    #
7240    fnot1\\t%1, %0"
7241   [(set_attr "type" "unary,fp")
7242    (set_attr "length" "2,1")])
7243
7244 (define_split
7245   [(set (match_operand:DI 0 "register_operand" "")
7246         (not:DI (match_operand:DI 1 "register_operand" "")))]
7247   "! TARGET_ARCH64
7248    && reload_completed
7249    && ((GET_CODE (operands[0]) == REG
7250         && REGNO (operands[0]) < 32)
7251        || (GET_CODE (operands[0]) == SUBREG
7252            && GET_CODE (SUBREG_REG (operands[0])) == REG
7253            && REGNO (SUBREG_REG (operands[0])) < 32))"
7254   [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
7255    (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
7256   "if (GET_CODE (operands[0]) == SUBREG)
7257      operands[0] = alter_subreg (operands[0]);
7258    operands[2] = gen_highpart (SImode, operands[0]);
7259    operands[3] = gen_highpart (SImode, operands[1]);
7260    operands[4] = gen_lowpart (SImode, operands[0]);
7261    operands[5] = gen_lowpart (SImode, operands[1]);")
7262
7263 (define_insn "*one_cmpldi2_sp64"
7264   [(set (match_operand:DI 0 "register_operand" "=r,b")
7265         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
7266   "TARGET_ARCH64"
7267   "@
7268    xnor\\t%%g0, %1, %0
7269    fnot1\\t%1, %0"
7270   [(set_attr "type" "unary,fp")
7271    (set_attr "length" "1")])
7272
7273 (define_expand "one_cmplsi2"
7274   [(set (match_operand:SI 0 "register_operand" "")
7275         (not:SI (match_operand:SI 1 "arith_operand" "")))]
7276   ""
7277   "
7278 {
7279   if (TARGET_LIVE_G0
7280       && GET_CODE (operands[1]) == CONST_INT)
7281     {
7282       rtx zero_reg = gen_reg_rtx (SImode);
7283
7284       emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
7285       emit_insn (gen_rtx_SET (VOIDmode,
7286                               operands[0],
7287                               gen_rtx_NOT (SImode,
7288                                            gen_rtx_XOR (SImode,
7289                                                         zero_reg,
7290                                                         operands[1]))));
7291       DONE;
7292     }
7293 }")
7294
7295 (define_insn "*one_cmplsi2_not_liveg0"
7296   [(set (match_operand:SI 0 "register_operand" "=r,d")
7297         (not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
7298   "! TARGET_LIVE_G0"
7299   "@
7300   xnor\\t%%g0, %1, %0
7301   fnot1s\\t%1, %0"
7302   [(set_attr "type" "unary,fp")
7303    (set_attr "length" "1,1")])
7304
7305 (define_insn "*one_cmplsi2_liveg0"
7306   [(set (match_operand:SI 0 "register_operand" "=r,d")
7307         (not:SI (match_operand:SI 1 "arith_operand" "r,d")))]
7308   "TARGET_LIVE_G0"
7309   "@
7310   xnor\\t%1, 0, %0
7311   fnot1s\\t%1, %0"
7312   [(set_attr "type" "unary,fp")
7313    (set_attr "length" "1,1")])
7314
7315 (define_insn "*cmp_cc_not"
7316   [(set (reg:CC 100)
7317         (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
7318                     (const_int 0)))]
7319   "! TARGET_LIVE_G0"
7320   "xnorcc\\t%%g0, %0, %%g0"
7321   [(set_attr "type" "compare")
7322    (set_attr "length" "1")])
7323
7324 (define_insn "*cmp_ccx_not"
7325   [(set (reg:CCX 100)
7326         (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
7327                      (const_int 0)))]
7328   "TARGET_ARCH64"
7329   "xnorcc\\t%%g0, %0, %%g0"
7330   [(set_attr "type" "compare")
7331    (set_attr "length" "1")])
7332
7333 (define_insn "*cmp_cc_set_not"
7334   [(set (reg:CC 100)
7335         (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
7336                     (const_int 0)))
7337    (set (match_operand:SI 0 "register_operand" "=r")
7338         (not:SI (match_dup 1)))]
7339   "! TARGET_LIVE_G0"
7340   "xnorcc\\t%%g0, %1, %0"
7341   [(set_attr "type" "compare")
7342    (set_attr "length" "1")])
7343
7344 (define_insn "*cmp_ccx_set_not"
7345   [(set (reg:CCX 100)
7346         (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
7347                     (const_int 0)))
7348    (set (match_operand:DI 0 "register_operand" "=r")
7349         (not:DI (match_dup 1)))]
7350   "TARGET_ARCH64"
7351   "xnorcc\\t%%g0, %1, %0"
7352   [(set_attr "type" "compare")
7353    (set_attr "length" "1")])
7354 \f
7355 ;; Floating point arithmetic instructions.
7356
7357 (define_expand "addtf3"
7358   [(set (match_operand:TF 0 "nonimmediate_operand" "")
7359         (plus:TF (match_operand:TF 1 "general_operand" "")
7360                  (match_operand:TF 2 "general_operand" "")))]
7361   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
7362   "
7363 {
7364   if (! TARGET_HARD_QUAD)
7365     {
7366       rtx slot0, slot1, slot2;
7367
7368       if (GET_CODE (operands[0]) != MEM)
7369         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7370       else
7371         slot0 = operands[0];
7372       if (GET_CODE (operands[1]) != MEM)
7373         {
7374           slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7375           emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
7376         }
7377       else
7378         slot1 = operands[1];
7379       if (GET_CODE (operands[2]) != MEM)
7380         {
7381           slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7382           emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
7383         }
7384       else
7385         slot2 = operands[2];
7386
7387       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_add\"), 0,
7388                          VOIDmode, 3,
7389                          XEXP (slot0, 0), Pmode,
7390                          XEXP (slot1, 0), Pmode,
7391                          XEXP (slot2, 0), Pmode);
7392
7393       if (GET_CODE (operands[0]) != MEM)
7394         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
7395       DONE;
7396     }
7397 }")
7398
7399 (define_insn "*addtf3_hq"
7400   [(set (match_operand:TF 0 "register_operand" "=e")
7401         (plus:TF (match_operand:TF 1 "register_operand" "e")
7402                  (match_operand:TF 2 "register_operand" "e")))]
7403   "TARGET_FPU && TARGET_HARD_QUAD"
7404   "faddq\\t%1, %2, %0"
7405   [(set_attr "type" "fp")
7406    (set_attr "length" "1")])
7407
7408 (define_insn "adddf3"
7409   [(set (match_operand:DF 0 "register_operand" "=e")
7410         (plus:DF (match_operand:DF 1 "register_operand" "e")
7411                  (match_operand:DF 2 "register_operand" "e")))]
7412   "TARGET_FPU"
7413   "faddd\\t%1, %2, %0"
7414   [(set_attr "type" "fp")
7415    (set_attr "length" "1")])
7416
7417 (define_insn "addsf3"
7418   [(set (match_operand:SF 0 "register_operand" "=f")
7419         (plus:SF (match_operand:SF 1 "register_operand" "f")
7420                  (match_operand:SF 2 "register_operand" "f")))]
7421   "TARGET_FPU"
7422   "fadds\\t%1, %2, %0"
7423   [(set_attr "type" "fp")
7424    (set_attr "length" "1")])
7425
7426 (define_expand "subtf3"
7427   [(set (match_operand:TF 0 "nonimmediate_operand" "")
7428         (minus:TF (match_operand:TF 1 "general_operand" "")
7429                   (match_operand:TF 2 "general_operand" "")))]
7430   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
7431   "
7432 {
7433   if (! TARGET_HARD_QUAD)
7434     {
7435       rtx slot0, slot1, slot2;
7436
7437       if (GET_CODE (operands[0]) != MEM)
7438         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7439       else
7440         slot0 = operands[0];
7441       if (GET_CODE (operands[1]) != MEM)
7442         {
7443           slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7444           emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
7445         }
7446       else
7447         slot1 = operands[1];
7448       if (GET_CODE (operands[2]) != MEM)
7449         {
7450           slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7451           emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
7452         }
7453       else
7454         slot2 = operands[2];
7455
7456       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sub\"), 0,
7457                          VOIDmode, 3,
7458                          XEXP (slot0, 0), Pmode,
7459                          XEXP (slot1, 0), Pmode,
7460                          XEXP (slot2, 0), Pmode);
7461
7462       if (GET_CODE (operands[0]) != MEM)
7463         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
7464       DONE;
7465     }
7466 }")
7467
7468 (define_insn "*subtf3_hq"
7469   [(set (match_operand:TF 0 "register_operand" "=e")
7470         (minus:TF (match_operand:TF 1 "register_operand" "e")
7471                   (match_operand:TF 2 "register_operand" "e")))]
7472   "TARGET_FPU && TARGET_HARD_QUAD"
7473   "fsubq\\t%1, %2, %0"
7474   [(set_attr "type" "fp")
7475    (set_attr "length" "1")])
7476
7477 (define_insn "subdf3"
7478   [(set (match_operand:DF 0 "register_operand" "=e")
7479         (minus:DF (match_operand:DF 1 "register_operand" "e")
7480                   (match_operand:DF 2 "register_operand" "e")))]
7481   "TARGET_FPU"
7482   "fsubd\\t%1, %2, %0"
7483   [(set_attr "type" "fp")
7484    (set_attr "length" "1")])
7485
7486 (define_insn "subsf3"
7487   [(set (match_operand:SF 0 "register_operand" "=f")
7488         (minus:SF (match_operand:SF 1 "register_operand" "f")
7489                   (match_operand:SF 2 "register_operand" "f")))]
7490   "TARGET_FPU"
7491   "fsubs\\t%1, %2, %0"
7492   [(set_attr "type" "fp")
7493    (set_attr "length" "1")])
7494
7495 (define_expand "multf3"
7496   [(set (match_operand:TF 0 "nonimmediate_operand" "")
7497         (mult:TF (match_operand:TF 1 "general_operand" "")
7498                  (match_operand:TF 2 "general_operand" "")))]
7499   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
7500   "
7501 {
7502   if (! TARGET_HARD_QUAD)
7503     {
7504       rtx slot0, slot1, slot2;
7505
7506       if (GET_CODE (operands[0]) != MEM)
7507         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7508       else
7509         slot0 = operands[0];
7510       if (GET_CODE (operands[1]) != MEM)
7511         {
7512           slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7513           emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
7514         }
7515       else
7516         slot1 = operands[1];
7517       if (GET_CODE (operands[2]) != MEM)
7518         {
7519           slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7520           emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
7521         }
7522       else
7523         slot2 = operands[2];
7524
7525       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_mul\"), 0,
7526                          VOIDmode, 3,
7527                          XEXP (slot0, 0), Pmode,
7528                          XEXP (slot1, 0), Pmode,
7529                          XEXP (slot2, 0), Pmode);
7530
7531       if (GET_CODE (operands[0]) != MEM)
7532         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
7533       DONE;
7534     }
7535 }")
7536
7537 (define_insn "*multf3_hq"
7538   [(set (match_operand:TF 0 "register_operand" "=e")
7539         (mult:TF (match_operand:TF 1 "register_operand" "e")
7540                  (match_operand:TF 2 "register_operand" "e")))]
7541   "TARGET_FPU && TARGET_HARD_QUAD"
7542   "fmulq\\t%1, %2, %0"
7543   [(set_attr "type" "fpmul")
7544    (set_attr "length" "1")])
7545
7546 (define_insn "muldf3"
7547   [(set (match_operand:DF 0 "register_operand" "=e")
7548         (mult:DF (match_operand:DF 1 "register_operand" "e")
7549                  (match_operand:DF 2 "register_operand" "e")))]
7550   "TARGET_FPU"
7551   "fmuld\\t%1, %2, %0"
7552   [(set_attr "type" "fpmul")
7553    (set_attr "length" "1")])
7554
7555 (define_insn "mulsf3"
7556   [(set (match_operand:SF 0 "register_operand" "=f")
7557         (mult:SF (match_operand:SF 1 "register_operand" "f")
7558                  (match_operand:SF 2 "register_operand" "f")))]
7559   "TARGET_FPU"
7560   "fmuls\\t%1, %2, %0"
7561   [(set_attr "type" "fpmul")
7562    (set_attr "length" "1")])
7563
7564 (define_insn "*muldf3_extend"
7565   [(set (match_operand:DF 0 "register_operand" "=e")
7566         (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
7567                  (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
7568   "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
7569   "fsmuld\\t%1, %2, %0"
7570   [(set_attr "type" "fpmul")
7571    (set_attr "length" "1")])
7572
7573 (define_insn "*multf3_extend"
7574   [(set (match_operand:TF 0 "register_operand" "=e")
7575         (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
7576                  (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
7577   "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
7578   "fdmulq\\t%1, %2, %0"
7579   [(set_attr "type" "fpmul")
7580    (set_attr "length" "1")])
7581
7582 (define_expand "divtf3"
7583   [(set (match_operand:TF 0 "nonimmediate_operand" "")
7584         (div:TF (match_operand:TF 1 "general_operand" "")
7585                 (match_operand:TF 2 "general_operand" "")))]
7586   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
7587   "
7588 {
7589   if (! TARGET_HARD_QUAD)
7590     {
7591       rtx slot0, slot1, slot2;
7592
7593       if (GET_CODE (operands[0]) != MEM)
7594         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7595       else
7596         slot0 = operands[0];
7597       if (GET_CODE (operands[1]) != MEM)
7598         {
7599           slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7600           emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
7601         }
7602       else
7603         slot1 = operands[1];
7604       if (GET_CODE (operands[2]) != MEM)
7605         {
7606           slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7607           emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
7608         }
7609       else
7610         slot2 = operands[2];
7611
7612       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_div\"), 0,
7613                          VOIDmode, 3,
7614                          XEXP (slot0, 0), Pmode,
7615                          XEXP (slot1, 0), Pmode,
7616                          XEXP (slot2, 0), Pmode);
7617
7618       if (GET_CODE (operands[0]) != MEM)
7619         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
7620       DONE;
7621     }
7622 }")
7623
7624 ;; don't have timing for quad-prec. divide.
7625 (define_insn "*divtf3_hq"
7626   [(set (match_operand:TF 0 "register_operand" "=e")
7627         (div:TF (match_operand:TF 1 "register_operand" "e")
7628                 (match_operand:TF 2 "register_operand" "e")))]
7629   "TARGET_FPU && TARGET_HARD_QUAD"
7630   "fdivq\\t%1, %2, %0"
7631   [(set_attr "type" "fpdivd")
7632    (set_attr "length" "1")])
7633
7634 (define_insn "divdf3"
7635   [(set (match_operand:DF 0 "register_operand" "=e")
7636         (div:DF (match_operand:DF 1 "register_operand" "e")
7637                 (match_operand:DF 2 "register_operand" "e")))]
7638   "TARGET_FPU"
7639   "fdivd\\t%1, %2, %0"
7640   [(set_attr "type" "fpdivd")
7641    (set_attr "length" "1")])
7642
7643 (define_insn "divsf3"
7644   [(set (match_operand:SF 0 "register_operand" "=f")
7645         (div:SF (match_operand:SF 1 "register_operand" "f")
7646                 (match_operand:SF 2 "register_operand" "f")))]
7647   "TARGET_FPU"
7648   "fdivs\\t%1, %2, %0"
7649   [(set_attr "type" "fpdivs")
7650    (set_attr "length" "1")])
7651
7652 (define_expand "negtf2"
7653   [(set (match_operand:TF 0 "register_operand" "=e,e")
7654         (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
7655   "TARGET_FPU"
7656   "")
7657
7658 (define_insn "*negtf2_notv9"
7659   [(set (match_operand:TF 0 "register_operand" "=e,e")
7660         (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
7661   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
7662   "TARGET_FPU
7663    && ! TARGET_V9"
7664   "@
7665   fnegs\\t%0, %0
7666   #"
7667   [(set_attr "type" "fpmove")
7668    (set_attr "length" "1,2")])
7669
7670 (define_split
7671   [(set (match_operand:TF 0 "register_operand" "")
7672         (neg:TF (match_operand:TF 1 "register_operand" "")))]
7673   "TARGET_FPU
7674    && ! TARGET_V9
7675    && reload_completed
7676    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7677   [(set (match_dup 2) (neg:SF (match_dup 3)))
7678    (set (match_dup 4) (match_dup 5))
7679    (set (match_dup 6) (match_dup 7))]
7680   "if (GET_CODE (operands[0]) == SUBREG)
7681      operands[0] = alter_subreg (operands[0]);
7682    if (GET_CODE (operands[1]) == SUBREG)
7683      operands[1] = alter_subreg (operands[1]);
7684    operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
7685    operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
7686    operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
7687    operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
7688    operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
7689    operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
7690
7691 (define_insn "*negtf2_v9"
7692   [(set (match_operand:TF 0 "register_operand" "=e,e")
7693         (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
7694   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
7695   "TARGET_FPU && TARGET_V9"
7696   "@
7697   fnegd\\t%0, %0
7698   #"
7699   [(set_attr "type" "fpmove")
7700    (set_attr "length" "1,2")])
7701
7702 (define_split
7703   [(set (match_operand:TF 0 "register_operand" "")
7704         (neg:TF (match_operand:TF 1 "register_operand" "")))]
7705   "TARGET_FPU
7706    && TARGET_V9
7707    && reload_completed
7708    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7709   [(set (match_dup 2) (neg:DF (match_dup 3)))
7710    (set (match_dup 4) (match_dup 5))]
7711   "if (GET_CODE (operands[0]) == SUBREG)
7712      operands[0] = alter_subreg (operands[0]);
7713    if (GET_CODE (operands[1]) == SUBREG)
7714      operands[1] = alter_subreg (operands[1]);
7715    operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
7716    operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
7717    operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
7718    operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
7719
7720 (define_expand "negdf2"
7721   [(set (match_operand:DF 0 "register_operand" "")
7722         (neg:DF (match_operand:DF 1 "register_operand" "")))]
7723   "TARGET_FPU"
7724   "")
7725
7726 (define_insn "*negdf2_notv9"
7727   [(set (match_operand:DF 0 "register_operand" "=e,e")
7728         (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
7729   "TARGET_FPU && ! TARGET_V9"
7730   "@
7731   fnegs\\t%0, %0
7732   #"
7733   [(set_attr "type" "fpmove")
7734    (set_attr "length" "1,2")])
7735
7736 (define_split
7737   [(set (match_operand:DF 0 "register_operand" "")
7738         (neg:DF (match_operand:DF 1 "register_operand" "")))]
7739   "TARGET_FPU
7740    && ! TARGET_V9
7741    && reload_completed
7742    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7743   [(set (match_dup 2) (neg:SF (match_dup 3)))
7744    (set (match_dup 4) (match_dup 5))]
7745   "if (GET_CODE (operands[0]) == SUBREG)
7746      operands[0] = alter_subreg (operands[0]);
7747    if (GET_CODE (operands[1]) == SUBREG)
7748      operands[1] = alter_subreg (operands[1]);
7749    operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
7750    operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
7751    operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
7752    operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
7753
7754 (define_insn "*negdf2_v9"
7755   [(set (match_operand:DF 0 "register_operand" "=e")
7756         (neg:DF (match_operand:DF 1 "register_operand" "e")))]
7757   "TARGET_FPU && TARGET_V9"
7758   "fnegd\\t%1, %0"
7759   [(set_attr "type" "fpmove")
7760    (set_attr "length" "1")])
7761
7762 (define_insn "negsf2"
7763   [(set (match_operand:SF 0 "register_operand" "=f")
7764         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
7765   "TARGET_FPU"
7766   "fnegs\\t%1, %0"
7767   [(set_attr "type" "fpmove")
7768    (set_attr "length" "1")])
7769
7770 (define_expand "abstf2"
7771   [(set (match_operand:TF 0 "register_operand" "")
7772         (abs:TF (match_operand:TF 1 "register_operand" "")))]
7773   "TARGET_FPU"
7774   "")
7775
7776 (define_insn "*abstf2_notv9"
7777   [(set (match_operand:TF 0 "register_operand" "=e,e")
7778         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
7779   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
7780   "TARGET_FPU && ! TARGET_V9"
7781   "@
7782   fabss\\t%0, %0
7783   #"
7784   [(set_attr "type" "fpmove")
7785    (set_attr "length" "1,2")])
7786
7787 (define_split
7788   [(set (match_operand:TF 0 "register_operand" "=e,e")
7789         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
7790   "TARGET_FPU
7791    && ! TARGET_V9
7792    && reload_completed
7793    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7794   [(set (match_dup 2) (abs:SF (match_dup 3)))
7795    (set (match_dup 4) (match_dup 5))
7796    (set (match_dup 6) (match_dup 7))]
7797   "if (GET_CODE (operands[0]) == SUBREG)
7798      operands[0] = alter_subreg (operands[0]);
7799    if (GET_CODE (operands[1]) == SUBREG)
7800      operands[1] = alter_subreg (operands[1]);
7801    operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
7802    operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
7803    operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
7804    operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
7805    operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
7806    operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
7807
7808 (define_insn "*abstf2_hq_v9"
7809   [(set (match_operand:TF 0 "register_operand" "=e,e")
7810         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
7811   "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
7812   "@
7813   fabsd\\t%0, %0
7814   fabsq\\t%1, %0"
7815   [(set_attr "type" "fpmove")
7816    (set_attr "length" "1")])
7817
7818 (define_insn "*abstf2_v9"
7819   [(set (match_operand:TF 0 "register_operand" "=e,e")
7820         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
7821   "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
7822   "@
7823   fabsd\\t%0, %0
7824   #"
7825   [(set_attr "type" "fpmove")
7826    (set_attr "length" "1,2")])
7827
7828 (define_split
7829   [(set (match_operand:TF 0 "register_operand" "=e,e")
7830         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
7831   "TARGET_FPU
7832    && TARGET_V9
7833    && reload_completed
7834    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7835   [(set (match_dup 2) (abs:DF (match_dup 3)))
7836    (set (match_dup 4) (match_dup 5))]
7837   "if (GET_CODE (operands[0]) == SUBREG)
7838      operands[0] = alter_subreg (operands[0]);
7839    if (GET_CODE (operands[1]) == SUBREG)
7840      operands[1] = alter_subreg (operands[1]);
7841    operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
7842    operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
7843    operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
7844    operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
7845
7846 (define_expand "absdf2"
7847   [(set (match_operand:DF 0 "register_operand" "")
7848         (abs:DF (match_operand:DF 1 "register_operand" "")))]
7849   "TARGET_FPU"
7850   "")
7851
7852 (define_insn "*absdf2_notv9"
7853   [(set (match_operand:DF 0 "register_operand" "=e,e")
7854         (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
7855   "TARGET_FPU && ! TARGET_V9"
7856   "@
7857   fabss\\t%0, %0
7858   #"
7859   [(set_attr "type" "fpmove")
7860    (set_attr "length" "1,2")])
7861
7862 (define_split
7863   [(set (match_operand:DF 0 "register_operand" "=e,e")
7864         (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
7865   "TARGET_FPU
7866    && ! TARGET_V9
7867    && reload_completed
7868    && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
7869   [(set (match_dup 2) (abs:SF (match_dup 3)))
7870    (set (match_dup 4) (match_dup 5))]
7871   "if (GET_CODE (operands[0]) == SUBREG)
7872      operands[0] = alter_subreg (operands[0]);
7873    if (GET_CODE (operands[1]) == SUBREG)
7874      operands[1] = alter_subreg (operands[1]);
7875    operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
7876    operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
7877    operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
7878    operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
7879
7880 (define_insn "*absdf2_v9"
7881   [(set (match_operand:DF 0 "register_operand" "=e")
7882         (abs:DF (match_operand:DF 1 "register_operand" "e")))]
7883   "TARGET_FPU && TARGET_V9"
7884   "fabsd\\t%1, %0"
7885   [(set_attr "type" "fpmove")
7886    (set_attr "length" "1")])
7887
7888 (define_insn "abssf2"
7889   [(set (match_operand:SF 0 "register_operand" "=f")
7890         (abs:SF (match_operand:SF 1 "register_operand" "f")))]
7891   "TARGET_FPU"
7892   "fabss\\t%1, %0"
7893   [(set_attr "type" "fpmove")
7894    (set_attr "length" "1")])
7895
7896 (define_expand "sqrttf2"
7897   [(set (match_operand:TF 0 "register_operand" "=e")
7898         (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
7899   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
7900   "
7901 {
7902   if (! TARGET_HARD_QUAD)
7903     {
7904       rtx slot0, slot1;
7905
7906       if (GET_CODE (operands[0]) != MEM)
7907         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7908       else
7909         slot0 = operands[0];
7910       if (GET_CODE (operands[1]) != MEM)
7911         {
7912           slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
7913           emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
7914         }
7915       else
7916         slot1 = operands[1];
7917
7918       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sqrt\"), 0,
7919                          VOIDmode, 2,
7920                          XEXP (slot0, 0), Pmode,
7921                          XEXP (slot1, 0), Pmode);
7922
7923       if (GET_CODE (operands[0]) != MEM)
7924         emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
7925       DONE;
7926     }
7927 }")
7928
7929 (define_insn "*sqrttf2_hq"
7930   [(set (match_operand:TF 0 "register_operand" "=e")
7931         (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
7932   "TARGET_FPU && TARGET_HARD_QUAD"
7933   "fsqrtq\\t%1, %0"
7934   [(set_attr "type" "fpsqrtd")
7935    (set_attr "length" "1")])
7936
7937 (define_insn "sqrtdf2"
7938   [(set (match_operand:DF 0 "register_operand" "=e")
7939         (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
7940   "TARGET_FPU"
7941   "fsqrtd\\t%1, %0"
7942   [(set_attr "type" "fpsqrtd")
7943    (set_attr "length" "1")])
7944
7945 (define_insn "sqrtsf2"
7946   [(set (match_operand:SF 0 "register_operand" "=f")
7947         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
7948   "TARGET_FPU"
7949   "fsqrts\\t%1, %0"
7950   [(set_attr "type" "fpsqrts")
7951    (set_attr "length" "1")])
7952 \f
7953 ;;- arithmetic shift instructions
7954
7955 (define_insn "ashlsi3"
7956   [(set (match_operand:SI 0 "register_operand" "=r")
7957         (ashift:SI (match_operand:SI 1 "register_operand" "r")
7958                    (match_operand:SI 2 "arith_operand" "rI")))]
7959   ""
7960   "*
7961 {
7962   if (GET_CODE (operands[2]) == CONST_INT
7963       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
7964     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
7965
7966   return \"sll\\t%1, %2, %0\";
7967 }"
7968   [(set_attr "type" "shift")
7969    (set_attr "length" "1")])
7970
7971 ;; We special case multiplication by two, as add can be done
7972 ;; in both ALUs, while shift only in IEU0 on UltraSPARC.
7973 (define_insn "*ashlsi3_const1"
7974   [(set (match_operand:SI 0 "register_operand" "=r")
7975         (ashift:SI (match_operand:SI 1 "register_operand" "r")
7976                    (const_int 1)))]
7977   ""
7978   "add\\t%1, %1, %0"
7979   [(set_attr "type" "binary")
7980    (set_attr "length" "1")])
7981
7982 (define_expand "ashldi3"
7983   [(set (match_operand:DI 0 "register_operand" "=r")
7984         (ashift:DI (match_operand:DI 1 "register_operand" "r")
7985                    (match_operand:SI 2 "arith_operand" "rI")))]
7986   "TARGET_ARCH64 || TARGET_V8PLUS"
7987   "
7988 {
7989   if (! TARGET_ARCH64)
7990     {
7991       if (GET_CODE (operands[2]) == CONST_INT)
7992         FAIL;
7993       emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
7994       DONE;
7995     }
7996 }")
7997
7998 ;; We special case multiplication by two, as add can be done
7999 ;; in both ALUs, while shift only in IEU0 on UltraSPARC.
8000 (define_insn "*ashldi3_const1"
8001   [(set (match_operand:DI 0 "register_operand" "=r")
8002         (ashift:DI (match_operand:DI 1 "register_operand" "r")
8003                    (const_int 1)))]
8004   "TARGET_ARCH64"
8005   "add\\t%1, %1, %0"
8006   [(set_attr "type" "binary")
8007    (set_attr "length" "1")])
8008
8009 (define_insn "*ashldi3_sp64"
8010   [(set (match_operand:DI 0 "register_operand" "=r")
8011         (ashift:DI (match_operand:DI 1 "register_operand" "r")
8012                    (match_operand:SI 2 "arith_operand" "rI")))]
8013   "TARGET_ARCH64"
8014   "*
8015 {
8016   if (GET_CODE (operands[2]) == CONST_INT
8017       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
8018     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
8019
8020   return \"sllx\\t%1, %2, %0\";
8021 }"
8022   [(set_attr "type" "shift")
8023    (set_attr "length" "1")])
8024
8025 ;; XXX UGH!
8026 (define_insn "ashldi3_v8plus"
8027   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
8028         (ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
8029                    (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
8030    (clobber (match_scratch:SI 3 "=X,X,&h"))]
8031   "TARGET_V8PLUS"
8032   "*return sparc_v8plus_shift (operands, insn, \"sllx\");"
8033   [(set_attr "length" "5,5,6")])
8034
8035 ;; Optimize (1LL<<x)-1
8036 ;; XXX this also needs to be fixed to handle equal subregs
8037 ;; XXX first before we could re-enable it.
8038 (define_insn ""
8039   [(set (match_operand:DI 0 "register_operand" "=h")
8040         (plus:DI (ashift:DI (const_int 1)
8041                             (match_operand:SI 2 "arith_operand" "rI"))
8042                  (const_int -1)))]
8043   "0 && TARGET_V8PLUS"
8044   "*
8045 {
8046   if (GET_CODE (operands[2]) == REG && REGNO (operands[2]) == REGNO (operands[0]))
8047     return \"mov 1,%L0\;sllx %L0,%2,%L0\;sub %L0,1,%L0\;srlx %L0,32,%H0\";
8048   return \"mov 1,%H0\;sllx %H0,%2,%L0\;sub %L0,1,%L0\;srlx %L0,32,%H0\";
8049 }"
8050   [(set_attr "length" "4")])
8051
8052 (define_insn "*cmp_cc_ashift_1"
8053   [(set (reg:CC_NOOV 100)
8054         (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
8055                                     (const_int 1))
8056                          (const_int 0)))]
8057   "! TARGET_LIVE_G0"
8058   "addcc\\t%0, %0, %%g0"
8059   [(set_attr "type" "compare")
8060    (set_attr "length" "1")])
8061
8062 (define_insn "*cmp_cc_set_ashift_1"
8063   [(set (reg:CC_NOOV 100)
8064         (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
8065                                     (const_int 1))
8066                          (const_int 0)))
8067    (set (match_operand:SI 0 "register_operand" "=r")
8068         (ashift:SI (match_dup 1) (const_int 1)))]
8069   ""
8070   "addcc\\t%1, %1, %0"
8071   [(set_attr "type" "compare")
8072    (set_attr "length" "1")])
8073
8074 (define_insn "ashrsi3"
8075   [(set (match_operand:SI 0 "register_operand" "=r")
8076         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
8077                      (match_operand:SI 2 "arith_operand" "rI")))]
8078   ""
8079   "*
8080 {
8081   if (GET_CODE (operands[2]) == CONST_INT
8082       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
8083     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
8084
8085   return \"sra\\t%1, %2, %0\";
8086 }"
8087   [(set_attr "type" "shift")
8088    (set_attr "length" "1")])
8089
8090 (define_insn "*ashrsi3_extend"
8091   [(set (match_operand:DI 0 "register_operand" "=r")
8092         (sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
8093                                      (match_operand:SI 2 "arith_operand" "r"))))]
8094   "TARGET_ARCH64"
8095   "sra\\t%1, %2, %0"
8096   [(set_attr "type" "shift")
8097    (set_attr "length" "1")])
8098
8099 ;; This handles the case as above, but with constant shift instead of
8100 ;; register. Combiner "simplifies" it for us a little bit though.
8101 (define_insn "*ashrsi3_extend2"
8102   [(set (match_operand:DI 0 "register_operand" "=r")
8103         (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
8104                                 (const_int 32))
8105                      (match_operand:SI 2 "small_int_or_double" "n")))]
8106   "TARGET_ARCH64
8107    && ((GET_CODE (operands[2]) == CONST_INT
8108         && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
8109        || (GET_CODE (operands[2]) == CONST_DOUBLE
8110            && !CONST_DOUBLE_HIGH (operands[2])
8111            && CONST_DOUBLE_LOW (operands[2]) >= 32
8112            && CONST_DOUBLE_LOW (operands[2]) < 64))"
8113   "*
8114 {
8115   operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
8116
8117   return \"sra\\t%1, %2, %0\";
8118 }"
8119   [(set_attr "type" "shift")
8120    (set_attr "length" "1")])
8121
8122 (define_expand "ashrdi3"
8123   [(set (match_operand:DI 0 "register_operand" "=r")
8124         (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
8125                      (match_operand:SI 2 "arith_operand" "rI")))]
8126   "TARGET_ARCH64 || TARGET_V8PLUS"
8127   "
8128 {
8129   if (! TARGET_ARCH64)
8130     {
8131       if (GET_CODE (operands[2]) == CONST_INT)
8132         FAIL;   /* prefer generic code in this case */
8133       emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
8134       DONE;
8135     }
8136 }")
8137
8138 (define_insn ""
8139   [(set (match_operand:DI 0 "register_operand" "=r")
8140         (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
8141                      (match_operand:SI 2 "arith_operand" "rI")))]
8142   "TARGET_ARCH64"
8143   "*
8144 {
8145   if (GET_CODE (operands[2]) == CONST_INT
8146       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
8147     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
8148
8149   return \"srax\\t%1, %2, %0\";
8150 }"
8151   [(set_attr "type" "shift")
8152    (set_attr "length" "1")])
8153
8154 ;; XXX
8155 (define_insn "ashrdi3_v8plus"
8156   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
8157         (ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
8158                      (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
8159    (clobber (match_scratch:SI 3 "=X,X,&h"))]
8160   "TARGET_V8PLUS"
8161   "*return sparc_v8plus_shift (operands, insn, \"srax\");"
8162   [(set_attr "length" "5,5,6")])
8163
8164 (define_insn "lshrsi3"
8165   [(set (match_operand:SI 0 "register_operand" "=r")
8166         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
8167                      (match_operand:SI 2 "arith_operand" "rI")))]
8168   ""
8169   "*
8170 {
8171   if (GET_CODE (operands[2]) == CONST_INT
8172       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
8173     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
8174
8175   return \"srl\\t%1, %2, %0\";
8176 }"
8177   [(set_attr "type" "shift")
8178    (set_attr "length" "1")])
8179
8180 ;; This handles the case where
8181 ;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
8182 ;; but combiner "simplifies" it for us.
8183 (define_insn "*lshrsi3_extend"
8184   [(set (match_operand:DI 0 "register_operand" "=r")
8185         (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
8186                            (match_operand:SI 2 "arith_operand" "r")) 0)
8187                 (match_operand 3 "" "")))]
8188   "TARGET_ARCH64
8189    && ((GET_CODE (operands[3]) == CONST_DOUBLE
8190            && CONST_DOUBLE_HIGH (operands[3]) == 0
8191            && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
8192 #if HOST_BITS_PER_WIDE_INT >= 64
8193           || (GET_CODE (operands[3]) == CONST_INT
8194               && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff)
8195 #endif
8196          )"
8197   "srl\\t%1, %2, %0"
8198   [(set_attr "type" "shift")
8199    (set_attr "length" "1")])
8200
8201 ;; This handles the case where
8202 ;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
8203 ;; but combiner "simplifies" it for us.
8204 (define_insn "*lshrsi3_extend2"
8205   [(set (match_operand:DI 0 "register_operand" "=r")
8206         (zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
8207                          (match_operand 2 "small_int_or_double" "n")
8208                          (const_int 32)))]
8209   "TARGET_ARCH64
8210    && ((GET_CODE (operands[2]) == CONST_INT
8211         && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
8212        || (GET_CODE (operands[2]) == CONST_DOUBLE
8213            && CONST_DOUBLE_HIGH (operands[2]) == 0
8214            && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
8215   "*
8216 {
8217   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
8218
8219   return \"srl\\t%1, %2, %0\";
8220 }"
8221   [(set_attr "type" "shift")
8222    (set_attr "length" "1")])
8223
8224 (define_expand "lshrdi3"
8225   [(set (match_operand:DI 0 "register_operand" "=r")
8226         (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
8227                      (match_operand:SI 2 "arith_operand" "rI")))]
8228   "TARGET_ARCH64 || TARGET_V8PLUS"
8229   "
8230 {
8231   if (! TARGET_ARCH64)
8232     {
8233       if (GET_CODE (operands[2]) == CONST_INT)
8234         FAIL;
8235       emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
8236       DONE;
8237     }
8238 }")
8239
8240 (define_insn ""
8241   [(set (match_operand:DI 0 "register_operand" "=r")
8242         (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
8243                      (match_operand:SI 2 "arith_operand" "rI")))]
8244   "TARGET_ARCH64"
8245   "*
8246 {
8247   if (GET_CODE (operands[2]) == CONST_INT
8248       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
8249     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
8250
8251   return \"srlx\\t%1, %2, %0\";
8252 }"
8253   [(set_attr "type" "shift")
8254    (set_attr "length" "1")])
8255
8256 ;; XXX
8257 (define_insn "lshrdi3_v8plus"
8258   [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
8259         (lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
8260                      (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
8261    (clobber (match_scratch:SI 3 "=X,X,&h"))]
8262   "TARGET_V8PLUS"
8263   "*return sparc_v8plus_shift (operands, insn, \"srlx\");"
8264   [(set_attr "length" "5,5,6")])
8265
8266 (define_insn ""
8267   [(set (match_operand:SI 0 "register_operand" "=r")
8268         (ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
8269                                              (const_int 32)) 0)
8270                      (match_operand:SI 2 "small_int_or_double" "n")))]
8271   "TARGET_ARCH64
8272    && ((GET_CODE (operands[2]) == CONST_INT
8273         && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
8274        || (GET_CODE (operands[2]) == CONST_DOUBLE
8275            && !CONST_DOUBLE_HIGH (operands[2])
8276            && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
8277   "*
8278 {
8279   operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
8280
8281   return \"srax\\t%1, %2, %0\";
8282 }"
8283   [(set_attr "type" "shift")
8284    (set_attr "length" "1")])
8285
8286 (define_insn ""
8287   [(set (match_operand:SI 0 "register_operand" "=r")
8288         (lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
8289                                              (const_int 32)) 0)
8290                      (match_operand:SI 2 "small_int_or_double" "n")))]
8291   "TARGET_ARCH64
8292    && ((GET_CODE (operands[2]) == CONST_INT
8293         && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
8294        || (GET_CODE (operands[2]) == CONST_DOUBLE
8295            && !CONST_DOUBLE_HIGH (operands[2])
8296            && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
8297   "*
8298 {
8299   operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
8300
8301   return \"srlx\\t%1, %2, %0\";
8302 }"
8303   [(set_attr "type" "shift")
8304    (set_attr "length" "1")])
8305
8306 (define_insn ""
8307   [(set (match_operand:SI 0 "register_operand" "=r")
8308         (ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
8309                                              (match_operand:SI 2 "small_int_or_double" "n")) 0)
8310                      (match_operand:SI 3 "small_int_or_double" "n")))]
8311   "TARGET_ARCH64
8312    && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
8313    && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
8314    && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
8315    && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
8316   "*
8317 {
8318   operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
8319
8320   return \"srax\\t%1, %2, %0\";
8321 }"
8322   [(set_attr "type" "shift")
8323    (set_attr "length" "1")])
8324
8325 (define_insn ""
8326   [(set (match_operand:SI 0 "register_operand" "=r")
8327         (lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
8328                                              (match_operand:SI 2 "small_int_or_double" "n")) 0)
8329                      (match_operand:SI 3 "small_int_or_double" "n")))]
8330   "TARGET_ARCH64
8331    && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
8332    && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
8333    && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
8334    && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
8335   "*
8336 {
8337   operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
8338
8339   return \"srlx\\t%1, %2, %0\";
8340 }"
8341   [(set_attr "type" "shift")
8342    (set_attr "length" "1")])
8343 \f
8344 ;; Unconditional and other jump instructions
8345 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
8346 ;; following insn is never executed.  This saves us a nop.  Dbx does not
8347 ;; handle such branches though, so we only use them when optimizing.
8348 (define_insn "jump"
8349   [(set (pc) (label_ref (match_operand 0 "" "")))]
8350   ""
8351   "*
8352 {
8353   /* TurboSparc is reported to have problems with
8354      with
8355         foo: b,a foo
8356      i.e. an empty loop with the annul bit set.  The workaround is to use 
8357         foo: b foo; nop
8358      instead.  */
8359
8360   if (! TARGET_V9 && flag_delayed_branch
8361       && (insn_addresses[INSN_UID (operands[0])]
8362           == insn_addresses[INSN_UID (insn)]))
8363     return \"b\\t%l0%#\";
8364   else
8365     return TARGET_V9 ? \"ba,pt%*\\t%%xcc, %l0%(\" : \"b%*\\t%l0%(\";
8366 }"
8367   [(set_attr "type" "uncond_branch")])
8368
8369 (define_expand "tablejump"
8370   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
8371               (use (label_ref (match_operand 1 "" "")))])]
8372   ""
8373   "
8374 {
8375   if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
8376     abort ();
8377
8378   /* In pic mode, our address differences are against the base of the
8379      table.  Add that base value back in; CSE ought to be able to combine
8380      the two address loads.  */
8381   if (flag_pic)
8382     {
8383       rtx tmp, tmp2;
8384       tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
8385       tmp2 = operands[0];
8386       if (CASE_VECTOR_MODE != Pmode)
8387         tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
8388       tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
8389       operands[0] = memory_address (Pmode, tmp);
8390     }
8391 }")
8392
8393 (define_insn "*tablejump_sp32"
8394   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
8395    (use (label_ref (match_operand 1 "" "")))]
8396   "! TARGET_PTR64"
8397   "jmp\\t%a0%#"
8398   [(set_attr "type" "uncond_branch")])
8399
8400 (define_insn "*tablejump_sp64"
8401   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
8402    (use (label_ref (match_operand 1 "" "")))]
8403   "TARGET_PTR64"
8404   "jmp\\t%a0%#"
8405   [(set_attr "type" "uncond_branch")])
8406
8407 ;; This pattern recognizes the "instruction" that appears in 
8408 ;; a function call that wants a structure value, 
8409 ;; to inform the called function if compiled with Sun CC.
8410 ;(define_insn "*unimp_insn"
8411 ;  [(match_operand:SI 0 "immediate_operand" "")]
8412 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
8413 ;  "unimp\\t%0"
8414 ;  [(set_attr "type" "marker")])
8415
8416 ;;- jump to subroutine
8417 (define_expand "call"
8418   ;; Note that this expression is not used for generating RTL.
8419   ;; All the RTL is generated explicitly below.
8420   [(call (match_operand 0 "call_operand" "")
8421          (match_operand 3 "" "i"))]
8422   ;; operands[2] is next_arg_register
8423   ;; operands[3] is struct_value_size_rtx.
8424   ""
8425   "
8426 {
8427   rtx fn_rtx, nregs_rtx;
8428
8429    if (GET_MODE (operands[0]) != FUNCTION_MODE)
8430     abort ();
8431
8432   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
8433     {
8434       /* This is really a PIC sequence.  We want to represent
8435          it as a funny jump so its delay slots can be filled. 
8436
8437          ??? But if this really *is* a CALL, will not it clobber the
8438          call-clobbered registers?  We lose this if it is a JUMP_INSN.
8439          Why cannot we have delay slots filled if it were a CALL?  */
8440
8441       if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
8442         emit_jump_insn
8443           (gen_rtx_PARALLEL
8444            (VOIDmode,
8445             gen_rtvec (3,
8446                        gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
8447                        operands[3],
8448                        gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
8449       else
8450         emit_jump_insn
8451           (gen_rtx_PARALLEL
8452            (VOIDmode,
8453             gen_rtvec (2,
8454                        gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
8455                        gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
8456       goto finish_call;
8457     }
8458
8459   fn_rtx = operands[0];
8460
8461   /* Count the number of parameter registers being used by this call.
8462      if that argument is NULL, it means we are using them all, which
8463      means 6 on the sparc.  */
8464 #if 0
8465   if (operands[2])
8466     nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
8467   else
8468     nregs_rtx = GEN_INT (6);
8469 #else
8470   nregs_rtx = const0_rtx;
8471 #endif
8472
8473   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
8474     emit_call_insn
8475       (gen_rtx_PARALLEL
8476        (VOIDmode,
8477         gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
8478                    operands[3],
8479                    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
8480   else
8481     emit_call_insn
8482       (gen_rtx_PARALLEL
8483        (VOIDmode,
8484         gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
8485                    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
8486
8487  finish_call:
8488 #if 0
8489   /* If this call wants a structure value,
8490      emit an unimp insn to let the called function know about this.  */
8491   if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
8492     {
8493       rtx insn = emit_insn (operands[3]);
8494       SCHED_GROUP_P (insn) = 1;
8495     }
8496 #endif
8497
8498   DONE;
8499 }")
8500
8501 ;; We can't use the same pattern for these two insns, because then registers
8502 ;; in the address may not be properly reloaded.
8503
8504 (define_insn "*call_address_sp32"
8505   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
8506          (match_operand 1 "" ""))
8507    (clobber (reg:SI 15))]
8508   ;;- Do not use operand 1 for most machines.
8509   "! TARGET_PTR64"
8510   "call\\t%a0, %1%#"
8511   [(set_attr "type" "call")])
8512
8513 (define_insn "*call_symbolic_sp32"
8514   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
8515          (match_operand 1 "" ""))
8516    (clobber (reg:SI 15))]
8517   ;;- Do not use operand 1 for most machines.
8518   "! TARGET_PTR64"
8519   "call\\t%a0, %1%#"
8520   [(set_attr "type" "call")])
8521
8522 (define_insn "*call_address_sp64"
8523   [(call (mem:SI (match_operand:DI 0 "address_operand" "p"))
8524          (match_operand 1 "" ""))
8525    (clobber (reg:DI 15))]
8526   ;;- Do not use operand 1 for most machines.
8527   "TARGET_PTR64"
8528   "call\\t%a0, %1%#"
8529   [(set_attr "type" "call")])
8530
8531 (define_insn "*call_symbolic_sp64"
8532   [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s"))
8533          (match_operand 1 "" ""))
8534    (clobber (reg:DI 15))]
8535   ;;- Do not use operand 1 for most machines.
8536   "TARGET_PTR64"
8537   "call\\t%a0, %1%#"
8538   [(set_attr "type" "call")])
8539
8540 ;; This is a call that wants a structure value.
8541 ;; There is no such critter for v9 (??? we may need one anyway).
8542 (define_insn "*call_address_struct_value_sp32"
8543   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
8544          (match_operand 1 "" ""))
8545    (match_operand 2 "immediate_operand" "")
8546    (clobber (reg:SI 15))]
8547   ;;- Do not use operand 1 for most machines.
8548   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
8549   "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
8550   [(set_attr "type" "call_no_delay_slot")])
8551
8552 ;; This is a call that wants a structure value.
8553 ;; There is no such critter for v9 (??? we may need one anyway).
8554 (define_insn "*call_symbolic_struct_value_sp32"
8555   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
8556          (match_operand 1 "" ""))
8557    (match_operand 2 "immediate_operand" "")
8558    (clobber (reg:SI 15))]
8559   ;;- Do not use operand 1 for most machines.
8560   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
8561   "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
8562   [(set_attr "type" "call_no_delay_slot")])
8563
8564 ;; This is a call that may want a structure value.  This is used for
8565 ;; untyped_calls.
8566 (define_insn "*call_address_untyped_struct_value_sp32"
8567   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
8568          (match_operand 1 "" ""))
8569    (match_operand 2 "immediate_operand" "")
8570    (clobber (reg:SI 15))]
8571   ;;- Do not use operand 1 for most machines.
8572   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
8573   "call\\t%a0, %1\\n\\tnop\\n\\tnop"
8574   [(set_attr "type" "call_no_delay_slot")])
8575
8576 ;; This is a call that wants a structure value.
8577 (define_insn "*call_symbolic_untyped_struct_value_sp32"
8578   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
8579          (match_operand 1 "" ""))
8580    (match_operand 2 "immediate_operand" "")
8581    (clobber (reg:SI 15))]
8582   ;;- Do not use operand 1 for most machines.
8583   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
8584   "call\\t%a0, %1\\n\\tnop\\n\\tnop"
8585   [(set_attr "type" "call_no_delay_slot")])
8586
8587 (define_expand "call_value"
8588   ;; Note that this expression is not used for generating RTL.
8589   ;; All the RTL is generated explicitly below.
8590   [(set (match_operand 0 "register_operand" "=rf")
8591         (call (match_operand:SI 1 "" "")
8592               (match_operand 4 "" "")))]
8593   ;; operand 2 is stack_size_rtx
8594   ;; operand 3 is next_arg_register
8595   ""
8596   "
8597 {
8598   rtx fn_rtx, nregs_rtx;
8599   rtvec vec;
8600
8601   if (GET_MODE (operands[1]) != FUNCTION_MODE)
8602     abort ();
8603
8604   fn_rtx = operands[1];
8605
8606 #if 0
8607   if (operands[3])
8608     nregs_rtx = GEN_INT (REGNO (operands[3]) - 8);
8609   else
8610     nregs_rtx = GEN_INT (6);
8611 #else
8612   nregs_rtx = const0_rtx;
8613 #endif
8614
8615   vec = gen_rtvec (2,
8616                    gen_rtx_SET (VOIDmode, operands[0],
8617                                 gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
8618                    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
8619
8620   emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
8621
8622   DONE;
8623 }")
8624
8625 (define_insn "*call_value_address_sp32"
8626   [(set (match_operand 0 "" "=rf")
8627         (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
8628               (match_operand 2 "" "")))
8629    (clobber (reg:SI 15))]
8630   ;;- Do not use operand 2 for most machines.
8631   "! TARGET_PTR64"
8632   "call\\t%a1, %2%#"
8633   [(set_attr "type" "call")])
8634
8635 (define_insn "*call_value_symbolic_sp32"
8636   [(set (match_operand 0 "" "=rf")
8637         (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
8638               (match_operand 2 "" "")))
8639    (clobber (reg:SI 15))]
8640   ;;- Do not use operand 2 for most machines.
8641   "! TARGET_PTR64"
8642   "call\\t%a1, %2%#"
8643   [(set_attr "type" "call")])
8644
8645 (define_insn "*call_value_address_sp64"
8646   [(set (match_operand 0 "" "")
8647         (call (mem:SI (match_operand:DI 1 "address_operand" "p"))
8648               (match_operand 2 "" "")))
8649    (clobber (reg:DI 15))]
8650   ;;- Do not use operand 2 for most machines.
8651   "TARGET_PTR64"
8652   "call\\t%a1, %2%#"
8653   [(set_attr "type" "call")])
8654
8655 (define_insn "*call_value_symbolic_sp64"
8656   [(set (match_operand 0 "" "")
8657         (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s"))
8658               (match_operand 2 "" "")))
8659    (clobber (reg:DI 15))]
8660   ;;- Do not use operand 2 for most machines.
8661   "TARGET_PTR64"
8662   "call\\t%a1, %2%#"
8663   [(set_attr "type" "call")])
8664
8665 (define_expand "untyped_call"
8666   [(parallel [(call (match_operand 0 "" "")
8667                     (const_int 0))
8668               (match_operand 1 "" "")
8669               (match_operand 2 "" "")])]
8670   ""
8671   "
8672 {
8673   int i;
8674
8675   /* Pass constm1 to indicate that it may expect a structure value, but
8676      we don't know what size it is.  */
8677   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
8678
8679   for (i = 0; i < XVECLEN (operands[2], 0); i++)
8680     {
8681       rtx set = XVECEXP (operands[2], 0, i);
8682       emit_move_insn (SET_DEST (set), SET_SRC (set));
8683     }
8684
8685   /* The optimizer does not know that the call sets the function value
8686      registers we stored in the result block.  We avoid problems by
8687      claiming that all hard registers are used and clobbered at this
8688      point.  */
8689   emit_insn (gen_blockage ());
8690
8691   DONE;
8692 }")
8693
8694 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8695 ;; all of memory.  This blocks insns from being moved across this point.
8696
8697 (define_insn "blockage"
8698   [(unspec_volatile [(const_int 0)] 0)]
8699   ""
8700   ""
8701   [(set_attr "length" "0")])
8702
8703 ;; Prepare to return any type including a structure value.
8704
8705 (define_expand "untyped_return"
8706   [(match_operand:BLK 0 "memory_operand" "")
8707    (match_operand 1 "" "")]
8708   ""
8709   "
8710 {
8711   rtx valreg1 = gen_rtx_REG (DImode, 24);
8712   rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
8713   rtx result = operands[0];
8714
8715   if (! TARGET_ARCH64)
8716     {
8717       rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
8718                                          ? 15 : 31));
8719       rtx value = gen_reg_rtx (SImode);
8720
8721       /* Fetch the instruction where we will return to and see if it's an unimp
8722          instruction (the most significant 10 bits will be zero).  If so,
8723          update the return address to skip the unimp instruction.  */
8724       emit_move_insn (value,
8725                       gen_rtx_MEM (SImode, plus_constant (rtnreg, 8)));
8726       emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
8727       emit_insn (gen_update_return (rtnreg, value));
8728     }
8729
8730   /* Reload the function value registers.  */
8731   emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
8732   emit_move_insn (valreg2,
8733                   change_address (result, TARGET_ARCH64 ? TFmode : DFmode,
8734                                   plus_constant (XEXP (result, 0), 8)));
8735
8736   /* Put USE insns before the return.  */
8737   emit_insn (gen_rtx_USE (VOIDmode, valreg1));
8738   emit_insn (gen_rtx_USE (VOIDmode, valreg2));
8739
8740   /* Construct the return.  */
8741   expand_null_return ();
8742
8743   DONE;
8744 }")
8745
8746 ;; This is a bit of a hack.  We're incrementing a fixed register (%i7),
8747 ;; and parts of the compiler don't want to believe that the add is needed.
8748
8749 (define_insn "update_return"
8750   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
8751                (match_operand:SI 1 "register_operand" "r")] 1)]
8752   "! TARGET_ARCH64"
8753   "cmp %1,0\;be,a .+8\;add %0,4,%0"
8754   [(set_attr "type" "multi")])
8755 \f
8756 (define_insn "return"
8757   [(return)
8758    (use (reg:SI 31))]
8759   "! TARGET_EPILOGUE"
8760   "* return output_return (operands);"
8761   [(set_attr "type" "return")])
8762
8763 (define_peephole
8764   [(set (match_operand:SI 0 "register_operand" "=r")
8765         (match_operand:SI 1 "arith_operand" "rI"))
8766    (parallel [(return)
8767               (use (reg:SI 31))])]
8768   "sparc_return_peephole_ok (operands[0], operands[1])"
8769   "return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0")
8770
8771 (define_insn "nop"
8772   [(const_int 0)]
8773   ""
8774   "nop"
8775   [(set_attr "type" "ialu")
8776    (set_attr "length" "1")])
8777
8778 (define_expand "indirect_jump"
8779   [(set (pc) (match_operand 0 "address_operand" "p"))]
8780   ""
8781   "")
8782
8783 (define_insn "*branch_sp32"
8784   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
8785   "! TARGET_PTR64"
8786  "jmp\\t%a0%#"
8787  [(set_attr "type" "uncond_branch")])
8788  
8789 (define_insn "*branch_sp64"
8790   [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
8791   "TARGET_PTR64"
8792   "jmp\\t%a0%#"
8793   [(set_attr "type" "uncond_branch")])
8794
8795 ;; ??? Doesn't work with -mflat.
8796 (define_expand "nonlocal_goto"
8797   [(match_operand:SI 0 "general_operand" "")
8798    (match_operand:SI 1 "general_operand" "")
8799    (match_operand:SI 2 "general_operand" "")
8800    (match_operand:SI 3 "" "")]
8801   ""
8802   "
8803 {
8804 #if 0
8805   rtx chain = operands[0];
8806 #endif
8807   rtx fp = operands[1];
8808   rtx stack = operands[2];
8809   rtx lab = operands[3];
8810   rtx labreg;
8811
8812   /* Trap instruction to flush all the register windows.  */
8813   emit_insn (gen_flush_register_windows ());
8814
8815   /* Load the fp value for the containing fn into %fp.  This is needed
8816      because STACK refers to %fp.  Note that virtual register instantiation
8817      fails if the virtual %fp isn't set from a register.  */
8818   if (GET_CODE (fp) != REG)
8819     fp = force_reg (Pmode, fp);
8820   emit_move_insn (virtual_stack_vars_rtx, fp);
8821
8822   /* Find the containing function's current nonlocal goto handler,
8823      which will do any cleanups and then jump to the label.  */
8824   labreg = gen_rtx_REG (Pmode, 8);
8825   emit_move_insn (labreg, lab);
8826
8827   /* Restore %fp from stack pointer value for containing function.
8828      The restore insn that follows will move this to %sp,
8829      and reload the appropriate value into %fp.  */
8830   emit_move_insn (frame_pointer_rtx, stack);
8831
8832   /* USE of frame_pointer_rtx added for consistency; not clear if
8833      really needed.  */
8834   /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
8835   emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
8836
8837 #if 0
8838   /* Return, restoring reg window and jumping to goto handler.  */
8839   if (TARGET_V9 && GET_CODE (chain) == CONST_INT
8840       && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
8841     {
8842       emit_insn (gen_goto_handler_and_restore_v9 (labreg, static_chain_rtx,
8843                                                   chain));
8844       emit_barrier ();
8845       DONE;
8846     }
8847   /* Put in the static chain register the nonlocal label address.  */
8848   emit_move_insn (static_chain_rtx, chain);
8849 #endif
8850
8851   emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
8852   emit_insn (gen_goto_handler_and_restore (labreg));
8853   emit_barrier ();
8854   DONE;
8855 }")
8856
8857 ;; Special trap insn to flush register windows.
8858 (define_insn "flush_register_windows"
8859   [(unspec_volatile [(const_int 0)] 1)]
8860   ""
8861   "* return TARGET_V9 ? \"flushw\" : \"ta\\t3\";"
8862   [(set_attr "type" "misc")
8863    (set_attr "length" "1")])
8864
8865 (define_insn "goto_handler_and_restore"
8866   [(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
8867   "GET_MODE (operands[0]) == Pmode"
8868   "jmp\\t%0+0\\n\\trestore"
8869   [(set_attr "type" "misc")
8870    (set_attr "length" "2")])
8871
8872 ;;(define_insn "goto_handler_and_restore_v9"
8873 ;;  [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
8874 ;;                   (match_operand:SI 1 "register_operand" "=r,r")
8875 ;;                   (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
8876 ;;  "TARGET_V9 && ! TARGET_ARCH64"
8877 ;;  "@
8878 ;;   return\\t%0+0\\n\\tmov\\t%2, %Y1
8879 ;;   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
8880 ;;  [(set_attr "type" "misc")
8881 ;;   (set_attr "length" "2,3")])
8882 ;;
8883 ;;(define_insn "*goto_handler_and_restore_v9_sp64"
8884 ;;  [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
8885 ;;                   (match_operand:DI 1 "register_operand" "=r,r")
8886 ;;                   (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
8887 ;;  "TARGET_V9 && TARGET_ARCH64"
8888 ;;  "@
8889 ;;   return\\t%0+0\\n\\tmov\\t%2, %Y1
8890 ;;   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
8891 ;;  [(set_attr "type" "misc")
8892 ;;   (set_attr "length" "2,3")])
8893
8894 ;; Pattern for use after a setjmp to store FP and the return register
8895 ;; into the stack area.
8896
8897 (define_expand "setjmp"
8898   [(const_int 0)]
8899   ""
8900   "
8901 {
8902   if (TARGET_ARCH64)
8903     emit_insn (gen_setjmp_64 ());
8904   else
8905     emit_insn (gen_setjmp_32 ());
8906   DONE;
8907 }")
8908
8909 (define_expand "setjmp_32"
8910   [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
8911    (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
8912   ""
8913   "
8914 { operands[0] = frame_pointer_rtx; }")
8915
8916 (define_expand "setjmp_64"
8917   [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
8918    (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
8919   ""
8920   "
8921 { operands[0] = frame_pointer_rtx; }")
8922
8923 ;; Special pattern for the FLUSH instruction.
8924
8925 ; We do SImode and DImode versions of this to quiet down genrecog's complaints
8926 ; of the define_insn otherwise missing a mode.  We make "flush", aka
8927 ; gen_flush, the default one since sparc_initialize_trampoline uses
8928 ; it on SImode mem values.
8929
8930 (define_insn "flush"
8931   [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 3)]
8932   ""
8933   "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
8934   [(set_attr "type" "misc")])
8935
8936 (define_insn "flushdi"
8937   [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] 3)]
8938   ""
8939   "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
8940   [(set_attr "type" "misc")])
8941
8942 \f
8943 ;; find first set.
8944
8945 ;; The scan instruction searches from the most significant bit while ffs
8946 ;; searches from the least significant bit.  The bit index and treatment of
8947 ;; zero also differ.  It takes at least 7 instructions to get the proper
8948 ;; result.  Here is an obvious 8 instruction sequence.
8949
8950 ;; XXX
8951 (define_insn "ffssi2"
8952   [(set (match_operand:SI 0 "register_operand" "=&r")
8953         (ffs:SI (match_operand:SI 1 "register_operand" "r")))
8954    (clobber (match_scratch:SI 2 "=&r"))]
8955   "TARGET_SPARCLITE || TARGET_SPARCLET"
8956   "*
8957 {
8958   if (TARGET_LIVE_G0)
8959     output_asm_insn (\"and %%g0,0,%%g0\", operands);
8960   return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\";
8961 }"
8962   [(set_attr "type" "multi")
8963    (set_attr "length" "8")])
8964
8965 ;; ??? This should be a define expand, so that the extra instruction have
8966 ;; a chance of being optimized away.
8967
8968 ;; Disabled because none of the UltraSparcs implement popc.  The HAL R1
8969 ;; does, but no one uses that and we don't have a switch for it.
8970 ;
8971 ;(define_insn "ffsdi2"
8972 ;  [(set (match_operand:DI 0 "register_operand" "=&r")
8973 ;       (ffs:DI (match_operand:DI 1 "register_operand" "r")))
8974 ;   (clobber (match_scratch:DI 2 "=&r"))]
8975 ;  "TARGET_ARCH64"
8976 ;  "neg %1,%2\;xnor %1,%2,%2\;popc %2,%0\;movzr %1,0,%0"
8977 ;  [(set_attr "type" "multi")
8978 ;   (set_attr "length" "4")])
8979
8980
8981 \f
8982 ;; Peepholes go at the end.
8983
8984 ;; Optimize consecutive loads or stores into ldd and std when possible.
8985 ;; The conditions in which we do this are very restricted and are 
8986 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
8987
8988 (define_peephole
8989   [(set (match_operand:SI 0 "memory_operand" "")
8990       (const_int 0))
8991    (set (match_operand:SI 1 "memory_operand" "")
8992       (const_int 0))]
8993   "TARGET_V9
8994    && ! MEM_VOLATILE_P (operands[0])
8995    && ! MEM_VOLATILE_P (operands[1])
8996    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[1], 0))"
8997   "stx\\t%%g0, %0")
8998
8999 (define_peephole
9000   [(set (match_operand:SI 0 "memory_operand" "")
9001       (const_int 0))
9002    (set (match_operand:SI 1 "memory_operand" "")
9003       (const_int 0))]
9004   "TARGET_V9
9005    && ! MEM_VOLATILE_P (operands[0])
9006    && ! MEM_VOLATILE_P (operands[1])
9007    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[0], 0))"
9008   "stx\\t%%g0, %1")
9009
9010 (define_peephole
9011   [(set (match_operand:SI 0 "register_operand" "=rf")
9012         (match_operand:SI 1 "memory_operand" ""))
9013    (set (match_operand:SI 2 "register_operand" "=rf")
9014         (match_operand:SI 3 "memory_operand" ""))]
9015   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
9016    && ! MEM_VOLATILE_P (operands[1])
9017    && ! MEM_VOLATILE_P (operands[3])
9018    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 
9019   "ldd\\t%1, %0")
9020
9021 (define_peephole
9022   [(set (match_operand:SI 0 "memory_operand" "")
9023         (match_operand:SI 1 "register_operand" "rf"))
9024    (set (match_operand:SI 2 "memory_operand" "")
9025         (match_operand:SI 3 "register_operand" "rf"))]
9026   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
9027    && ! MEM_VOLATILE_P (operands[0])
9028    && ! MEM_VOLATILE_P (operands[2])
9029    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
9030   "std\\t%1, %0")
9031  
9032 (define_peephole
9033   [(set (match_operand:SF 0 "register_operand" "=fr")
9034         (match_operand:SF 1 "memory_operand" ""))
9035    (set (match_operand:SF 2 "register_operand" "=fr")
9036         (match_operand:SF 3 "memory_operand" ""))]
9037   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
9038    && ! MEM_VOLATILE_P (operands[1])
9039    && ! MEM_VOLATILE_P (operands[3])
9040    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
9041   "ldd\\t%1, %0")
9042
9043 (define_peephole
9044   [(set (match_operand:SF 0 "memory_operand" "")
9045         (match_operand:SF 1 "register_operand" "fr"))
9046    (set (match_operand:SF 2 "memory_operand" "")
9047         (match_operand:SF 3 "register_operand" "fr"))]
9048   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
9049   && ! MEM_VOLATILE_P (operands[0])
9050   && ! MEM_VOLATILE_P (operands[2])
9051   && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
9052   "std\\t%1, %0")
9053
9054 (define_peephole
9055   [(set (match_operand:SI 0 "register_operand" "=rf")
9056         (match_operand:SI 1 "memory_operand" ""))
9057    (set (match_operand:SI 2 "register_operand" "=rf")
9058         (match_operand:SI 3 "memory_operand" ""))]
9059   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
9060   && ! MEM_VOLATILE_P (operands[3])
9061   && ! MEM_VOLATILE_P (operands[1])
9062   && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
9063   "ldd\\t%3, %2")
9064
9065 (define_peephole
9066   [(set (match_operand:SI 0 "memory_operand" "")
9067         (match_operand:SI 1 "register_operand" "rf"))
9068    (set (match_operand:SI 2 "memory_operand" "")
9069         (match_operand:SI 3 "register_operand" "rf"))]
9070   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
9071   && ! MEM_VOLATILE_P (operands[2])
9072   && ! MEM_VOLATILE_P (operands[0])
9073   && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
9074   "std\\t%3, %2")
9075  
9076 (define_peephole
9077   [(set (match_operand:SF 0 "register_operand" "=fr")
9078         (match_operand:SF 1 "memory_operand" ""))
9079    (set (match_operand:SF 2 "register_operand" "=fr")
9080         (match_operand:SF 3 "memory_operand" ""))]
9081   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
9082   && ! MEM_VOLATILE_P (operands[3])
9083   && ! MEM_VOLATILE_P (operands[1])
9084   && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
9085   "ldd\\t%3, %2")
9086
9087 (define_peephole
9088   [(set (match_operand:SF 0 "memory_operand" "")
9089         (match_operand:SF 1 "register_operand" "fr"))
9090    (set (match_operand:SF 2 "memory_operand" "")
9091         (match_operand:SF 3 "register_operand" "fr"))]
9092   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
9093   && ! MEM_VOLATILE_P (operands[2])
9094   && ! MEM_VOLATILE_P (operands[0])
9095   && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
9096   "std\\t%3, %2")
9097  
9098 ;; Optimize the case of following a reg-reg move with a test
9099 ;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
9100 ;; This can result from a float to fix conversion.
9101
9102 (define_peephole
9103   [(set (match_operand:SI 0 "register_operand" "=r")
9104         (match_operand:SI 1 "register_operand" "r"))
9105    (set (reg:CC 100)
9106         (compare:CC (match_operand:SI 2 "register_operand" "r")
9107                     (const_int 0)))]
9108   "(rtx_equal_p (operands[2], operands[0])
9109     || rtx_equal_p (operands[2], operands[1]))
9110    && ! FP_REG_P (operands[0])
9111    && ! FP_REG_P (operands[1])"
9112   "orcc\\t%1, 0, %0")
9113
9114 (define_peephole
9115   [(set (match_operand:DI 0 "register_operand" "=r")
9116         (match_operand:DI 1 "register_operand" "r"))
9117    (set (reg:CCX 100)
9118         (compare:CCX (match_operand:DI 2 "register_operand" "r")
9119                     (const_int 0)))]
9120   "TARGET_ARCH64
9121    && (rtx_equal_p (operands[2], operands[0])
9122        || rtx_equal_p (operands[2], operands[1]))
9123    && ! FP_REG_P (operands[0])
9124    && ! FP_REG_P (operands[1])"
9125   "orcc\\t%1, 0, %0")
9126
9127 ;; Return peepholes.  First the "normal" ones.
9128 ;; These are necessary to catch insns ending up in the epilogue delay list.
9129
9130 (define_insn "*return_qi"
9131   [(set (match_operand:QI 0 "restore_operand" "")
9132         (match_operand:QI 1 "arith_operand" "rI"))
9133    (return)]
9134   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
9135   "*
9136 {
9137   if (! TARGET_ARCH64 && current_function_returns_struct)
9138     return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
9139   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
9140                          || IN_OR_GLOBAL_P (operands[1])))
9141     return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
9142   else
9143     return \"ret\\n\\trestore %%g0, %1, %Y0\";
9144 }"
9145   [(set_attr "type" "multi")])
9146
9147 (define_insn "*return_hi"
9148   [(set (match_operand:HI 0 "restore_operand" "")
9149         (match_operand:HI 1 "arith_operand" "rI"))
9150    (return)]
9151   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
9152   "*
9153 {
9154   if (! TARGET_ARCH64 && current_function_returns_struct)
9155     return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
9156   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
9157                          || IN_OR_GLOBAL_P (operands[1])))
9158     return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
9159   else
9160     return \"ret\;restore %%g0, %1, %Y0\";
9161 }"
9162   [(set_attr "type" "multi")])
9163
9164 (define_insn "*return_si"
9165   [(set (match_operand:SI 0 "restore_operand" "")
9166         (match_operand:SI 1 "arith_operand" "rI"))
9167    (return)]
9168   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
9169   "*
9170 {
9171   if (! TARGET_ARCH64 && current_function_returns_struct)
9172     return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
9173   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
9174                          || IN_OR_GLOBAL_P (operands[1])))
9175     return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
9176   else
9177     return \"ret\;restore %%g0, %1, %Y0\";
9178 }"
9179   [(set_attr "type" "multi")])
9180
9181 ;; The following pattern is only generated by delayed-branch scheduling,
9182 ;; when the insn winds up in the epilogue.  This can happen not only when
9183 ;; ! TARGET_FPU because we move complex types around by parts using
9184 ;; SF mode SUBREGs.
9185 (define_insn "*return_sf_no_fpu"
9186   [(set (match_operand:SF 0 "restore_operand" "=r")
9187         (match_operand:SF 1 "register_operand" "r"))
9188    (return)]
9189   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
9190   "*
9191 {
9192   if (! TARGET_ARCH64 && current_function_returns_struct)
9193     return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
9194   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
9195     return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
9196   else
9197     return \"ret\;restore %%g0, %1, %Y0\";
9198 }"
9199   [(set_attr "type" "multi")])
9200
9201 (define_insn "*return_addsi"
9202   [(set (match_operand:SI 0 "restore_operand" "")
9203         (plus:SI (match_operand:SI 1 "register_operand" "r")
9204                  (match_operand:SI 2 "arith_operand" "rI")))
9205    (return)]
9206   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
9207   "*
9208 {
9209   if (! TARGET_ARCH64 && current_function_returns_struct)
9210     return \"jmp\\t%%i7+12\\n\\trestore %r1, %2, %Y0\";
9211   /* If operands are global or in registers, can use return */
9212   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
9213            && (GET_CODE (operands[2]) == CONST_INT
9214                || IN_OR_GLOBAL_P (operands[2])))
9215     return \"return\\t%%i7+8\\n\\tadd\\t%Y1, %Y2, %Y0\";
9216   else
9217     return \"ret\;restore %r1, %2, %Y0\";
9218 }"
9219   [(set_attr "type" "multi")])
9220
9221 (define_insn "*return_losum_si"
9222   [(set (match_operand:SI 0 "restore_operand" "")
9223         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
9224                    (match_operand:SI 2 "immediate_operand" "in")))
9225    (return)]
9226   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0 && ! TARGET_CM_MEDMID"
9227   "*
9228 {
9229   if (! TARGET_ARCH64 && current_function_returns_struct)
9230     return \"jmp\\t%%i7+12\\n\\trestore %r1, %%lo(%a2), %Y0\";
9231   /* If operands are global or in registers, can use return */
9232   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
9233     return \"return\\t%%i7+8\\n\\tor\\t%Y1, %%lo(%a2), %Y0\";
9234   else
9235     return \"ret\;restore %r1, %%lo(%a2), %Y0\";
9236 }"
9237   [(set_attr "type" "multi")])
9238
9239 (define_insn "*return_di"
9240   [(set (match_operand:DI 0 "restore_operand" "")
9241         (match_operand:DI 1 "arith_double_operand" "rHI"))
9242    (return)]
9243   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
9244   "ret\;restore %%g0, %1, %Y0"
9245   [(set_attr "type" "multi")])
9246
9247 (define_insn "*return_adddi"
9248   [(set (match_operand:DI 0 "restore_operand" "")
9249         (plus:DI (match_operand:DI 1 "arith_operand" "%r")
9250                  (match_operand:DI 2 "arith_double_operand" "rHI")))
9251    (return)]
9252   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
9253   "ret\;restore %r1, %2, %Y0"
9254   [(set_attr "type" "multi")])
9255
9256 (define_insn "*return_losum_di"
9257   [(set (match_operand:DI 0 "restore_operand" "")
9258         (lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
9259                    (match_operand:DI 2 "immediate_operand" "in")))
9260    (return)]
9261   "TARGET_ARCH64 && ! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
9262   "ret\;restore %r1, %%lo(%a2), %Y0"
9263   [(set_attr "type" "multi")])
9264
9265 ;; The following pattern is only generated by delayed-branch scheduling,
9266 ;; when the insn winds up in the epilogue.
9267 (define_insn "*return_sf"
9268   [(set (reg:SF 32)
9269         (match_operand:SF 0 "register_operand" "f"))
9270    (return)]
9271   "! TARGET_EPILOGUE"
9272   "ret\;fmovs\\t%0, %%f0"
9273   [(set_attr "type" "multi")])
9274
9275 ;; Now peepholes to do a call followed by a jump.
9276
9277 (define_peephole
9278   [(parallel [(set (match_operand 0 "" "")
9279                    (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
9280                          (match_operand 2 "" "")))
9281               (clobber (reg:SI 15))])
9282    (set (pc) (label_ref (match_operand 3 "" "")))]
9283   "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
9284    && in_same_eh_region (insn, operands[3])
9285    && in_same_eh_region (insn, ins1)"
9286   "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
9287
9288 (define_peephole
9289   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
9290                     (match_operand 1 "" ""))
9291               (clobber (reg:SI 15))])
9292    (set (pc) (label_ref (match_operand 2 "" "")))]
9293   "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
9294    && in_same_eh_region (insn, operands[2])
9295    && in_same_eh_region (insn, ins1)"
9296   "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
9297
9298 (define_peephole
9299   [(parallel [(set (match_operand 0 "" "")
9300                    (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
9301                          (match_operand 2 "" "")))
9302               (clobber (reg:DI 15))])
9303    (set (pc) (label_ref (match_operand 3 "" "")))]
9304   "TARGET_ARCH64
9305    && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
9306    && in_same_eh_region (insn, operands[3])
9307    && in_same_eh_region (insn, ins1)"
9308   "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
9309
9310 (define_peephole
9311   [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
9312                     (match_operand 1 "" ""))
9313               (clobber (reg:DI 15))])
9314    (set (pc) (label_ref (match_operand 2 "" "")))]
9315   "TARGET_ARCH64
9316    && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
9317    && in_same_eh_region (insn, operands[2])
9318    && in_same_eh_region (insn, ins1)"
9319   "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
9320
9321 ;; After a nonlocal goto, we need to restore the PIC register, but only
9322 ;; if we need it.  So do nothing much here, but we'll check for this in
9323 ;; finalize_pic.
9324
9325 ;; Make sure this unspec_volatile number agrees with finalize_pic.
9326 (define_insn "nonlocal_goto_receiver"
9327   [(unspec_volatile [(const_int 0)] 5)]
9328   "flag_pic"
9329   ""
9330   [(set_attr "length" "0")])
9331 \f
9332 (define_insn "trap"
9333   [(trap_if (const_int 1) (const_int 5))]
9334   ""
9335   "ta\\t5"
9336   [(set_attr "type" "misc")
9337    (set_attr "length" "1")])
9338
9339 (define_expand "conditional_trap"
9340   [(trap_if (match_operator 0 "noov_compare_op"
9341                             [(match_dup 2) (match_dup 3)])
9342             (match_operand:SI 1 "arith_operand" ""))]
9343   ""
9344   "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
9345                                   sparc_compare_op0, sparc_compare_op1);
9346    operands[3] = const0_rtx;")
9347
9348 (define_insn ""
9349   [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
9350             (match_operand:SI 1 "arith_operand" "rM"))]
9351   ""
9352   "t%C0\\t%1"
9353   [(set_attr "type" "misc")
9354    (set_attr "length" "1")])
9355
9356 (define_insn ""
9357   [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
9358             (match_operand:SI 1 "arith_operand" "rM"))]
9359   "TARGET_V9"
9360   "t%C0\\t%%xcc, %1"
9361   [(set_attr "type" "misc")
9362    (set_attr "length" "1")])