OSDN Git Service

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