OSDN Git Service

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