OSDN Git Service

* config/sparc/sparc.md: Add calls to 'in_same_eh_region' in 4
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.md
1 ;;- Machine description for SPARC chip for GNU C compiler
2 ;;  Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
3 ;;  Contributed by Michael Tiemann (tiemann@cygnus.com)
4 ;;  64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
5 ;;  at Cygnus Support.
6
7 ;; This file is part of GNU CC.
8
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
26 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
27 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
28 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
29 ;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
30 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
31 ;;
32 ;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to
33 ;; test TARGET_LIVE_G0 if we have TARGET_ARCH64.
34
35 ;; Attribute for cpu type.
36 ;; These must match the values for enum processor_type in sparc.h.
37 (define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v8plus,v9,ultrasparc"
38   (const (symbol_ref "sparc_cpu_attr")))
39
40 ;; Attribute for the instruction set.
41 ;; At present we only need to distinguish v9/!v9, but for clarity we
42 ;; test TARGET_V8 too.
43 (define_attr "isa" "v6,v8,v9,sparclet"
44  (const
45   (cond [(symbol_ref "TARGET_V9") (const_string "v9")
46          (symbol_ref "TARGET_V8") (const_string "v8")
47          (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
48         (const_string "v6"))))
49
50 ;; Architecture size.
51 (define_attr "arch" "arch32bit,arch64bit"
52  (const
53   (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
54         (const_string "arch32bit"))))
55
56 ;; Whether -mlive-g0 is in effect.
57 (define_attr "live_g0" "no,yes"
58  (const
59   (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
60         (const_string "no"))))
61
62 ;; Insn type.  Used to default other attribute values.
63
64 ;; type "unary" insns have one input operand (1) and one output operand (0)
65 ;; type "binary" insns have two input operands (1,2) and one output (0)
66 ;; type "compare" insns have one or two input operands (0,1) and no output
67 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
68
69 (define_attr "type"
70   "move,unary,binary,compare,load,sload,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc"
71   (const_string "binary"))
72
73 ;; Set true if insn uses call-clobbered intermediate register.
74 (define_attr "use_clobbered" "false,true"
75   (if_then_else (and (eq_attr "type" "address")
76                      (match_operand 0 "clobbered_register" ""))
77                 (const_string "true")
78                 (const_string "false")))
79
80 ;; Length (in # of insns).
81 (define_attr "length" ""
82   (cond [(eq_attr "type" "load,sload,fpload")
83          (if_then_else (match_operand 1 "symbolic_memory_operand" "")
84                        (const_int 2) (const_int 1))
85
86          (eq_attr "type" "store,fpstore")
87          (if_then_else (match_operand 0 "symbolic_memory_operand" "")
88                        (const_int 2) (const_int 1))
89
90          (eq_attr "type" "address") (const_int 2)
91
92          (eq_attr "type" "binary")
93          (if_then_else (ior (match_operand 2 "arith_operand" "")
94                             (match_operand 2 "arith_double_operand" ""))
95                        (const_int 1) (const_int 3))
96
97          (eq_attr "type" "multi") (const_int 2)
98
99          (eq_attr "type" "move,unary")
100          (if_then_else (ior (match_operand 1 "arith_operand" "")
101                             (match_operand 1 "arith_double_operand" ""))
102                        (const_int 1) (const_int 2))]
103
104         (const_int 1)))
105
106 (define_asm_attributes
107   [(set_attr "length" "1")
108    (set_attr "type" "multi")])
109
110 ;; Attributes for instruction and branch scheduling
111
112 (define_attr "in_call_delay" "false,true"
113   (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
114                 (const_string "false")
115          (eq_attr "type" "load,fpload,store,fpstore")
116                 (if_then_else (eq_attr "length" "1")
117                               (const_string "true")
118                               (const_string "false"))
119          (eq_attr "type" "address")
120                 (if_then_else (eq_attr "use_clobbered" "false")
121                               (const_string "true")
122                               (const_string "false"))]
123         (if_then_else (eq_attr "length" "1")
124                       (const_string "true")
125                       (const_string "false"))))
126
127 (define_delay (eq_attr "type" "call")
128   [(eq_attr "in_call_delay" "true") (nil) (nil)])
129
130 ;; ??? Should implement the notion of predelay slots for floating point
131 ;; branches.  This would allow us to remove the nop always inserted before
132 ;; a floating point branch.
133
134 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
135 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
136 ;; This is because doing so will add several pipeline stalls to the path
137 ;; that the load/store did not come from.  Unfortunately, there is no way
138 ;; to prevent fill_eager_delay_slots from using load/store without completely
139 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
140 ;; because it prevents us from moving back the final store of inner loops.
141
142 (define_attr "in_branch_delay" "false,true"
143   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
144                      (eq_attr "length" "1"))
145                 (const_string "true")
146                 (const_string "false")))
147
148 (define_attr "in_uncond_branch_delay" "false,true"
149   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
150                      (eq_attr "length" "1"))
151                 (const_string "true")
152                 (const_string "false")))
153
154 (define_attr "in_annul_branch_delay" "false,true"
155   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
156                      (eq_attr "length" "1"))
157                 (const_string "true")
158                 (const_string "false")))
159
160 (define_delay (eq_attr "type" "branch")
161   [(eq_attr "in_branch_delay" "true")
162    (nil) (eq_attr "in_annul_branch_delay" "true")])
163
164 (define_delay (eq_attr "type" "uncond_branch")
165   [(eq_attr "in_uncond_branch_delay" "true")
166    (nil) (nil)])
167    
168 ;; Function units of the SPARC
169
170 ;; (define_function_unit {name} {num-units} {n-users} {test}
171 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
172
173 ;; The integer ALU.
174 ;; (Noted only for documentation; units that take one cycle do not need to
175 ;; be specified.)
176
177 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
178 ;; the inputs.
179
180 ;; (define_function_unit "alu" 1 0
181 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
182
183 ;; ---- cypress CY7C602 scheduling:
184 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
185
186 (define_function_unit "memory" 1 0 
187   (and (eq_attr "cpu" "cypress")
188     (eq_attr "type" "load,sload,fpload"))
189   2 2)
190
191 ;; SPARC has two floating-point units: the FP ALU,
192 ;; and the FP MUL/DIV/SQRT unit.
193 ;; Instruction timings on the CY7C602 are as follows
194 ;; FABSs        4
195 ;; FADDs/d      5/5
196 ;; FCMPs/d      4/4
197 ;; FDIVs/d      23/37
198 ;; FMOVs        4
199 ;; FMULs/d      5/7
200 ;; FNEGs        4
201 ;; FSQRTs/d     34/63
202 ;; FSUBs/d      5/5
203 ;; FdTOi/s      5/5
204 ;; FsTOi/d      5/5
205 ;; FiTOs/d      9/5
206
207 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
208 ;; More insns cause the chip to stall.
209
210 (define_function_unit "fp_alu" 1 0
211   (and (eq_attr "cpu" "cypress")
212     (eq_attr "type" "fp,fpmove"))
213   5 5)
214
215 (define_function_unit "fp_mds" 1 0
216   (and (eq_attr "cpu" "cypress")
217     (eq_attr "type" "fpmul"))
218   7 7)
219
220 (define_function_unit "fp_mds" 1 0
221   (and (eq_attr "cpu" "cypress")
222     (eq_attr "type" "fpdivs,fpdivd"))
223   37 37)
224
225 (define_function_unit "fp_mds" 1 0
226   (and (eq_attr "cpu" "cypress")
227     (eq_attr "type" "fpsqrt"))
228   63 63)
229
230 ;; ----- The TMS390Z55 scheduling
231 ;; The Supersparc can issue 1 - 3 insns per cycle: up to two integer,
232 ;; one ld/st, one fp.
233 ;; Memory delivers its result in one cycle to IU, zero cycles to FP
234
235 (define_function_unit "memory" 1 0
236   (and (eq_attr "cpu" "supersparc")
237     (eq_attr "type" "load,sload"))
238   1 1)
239
240 (define_function_unit "memory" 1 0
241   (and (eq_attr "cpu" "supersparc")
242     (eq_attr "type" "fpload"))
243   0 1)
244
245 (define_function_unit "memory" 1 0
246   (and (eq_attr "cpu" "supersparc")
247     (eq_attr "type" "store,fpstore"))
248   1 1)
249
250 (define_function_unit "shift" 1 0
251   (and (eq_attr "cpu" "supersparc")
252     (eq_attr "type" "shift"))
253   1 1)
254
255 ;; There are only two write ports to the integer register file
256 ;; A store also uses a write port
257
258 (define_function_unit "iwport" 2 0
259   (and (eq_attr "cpu" "supersparc")
260     (eq_attr "type" "load,sload,store,shift,ialu"))
261   1 1)
262
263 ;; Timings; throughput/latency
264 ;; FADD     1/3    add/sub, format conv, compar, abs, neg
265 ;; FMUL     1/3
266 ;; FDIVs    4/6
267 ;; FDIVd    7/9
268 ;; FSQRTs   6/8
269 ;; FSQRTd  10/12
270 ;; IMUL     4/4
271
272 (define_function_unit "fp_alu" 1 0
273   (and (eq_attr "cpu" "supersparc")
274     (eq_attr "type" "fp,fpmove,fpcmp"))
275   3 1)
276
277 (define_function_unit "fp_mds" 1 0
278   (and (eq_attr "cpu" "supersparc")
279     (eq_attr "type" "fpmul"))
280   3 1)
281
282 (define_function_unit "fp_mds" 1 0
283   (and (eq_attr "cpu" "supersparc")
284     (eq_attr "type" "fpdivs"))
285   6 4)
286
287 (define_function_unit "fp_mds" 1 0
288   (and (eq_attr "cpu" "supersparc")
289     (eq_attr "type" "fpdivd"))
290   9 7)
291
292 (define_function_unit "fp_mds" 1 0
293   (and (eq_attr "cpu" "supersparc")
294     (eq_attr "type" "fpsqrt"))
295   12 10)
296
297 (define_function_unit "fp_mds" 1 0
298   (and (eq_attr "cpu" "supersparc")
299     (eq_attr "type" "imul"))
300   4 4)
301
302 ;; ----- sparclet tsc701 scheduling
303 ;; The tsc701 issues 1 insn per cycle.
304 ;; Results may be written back out of order.
305
306 ;; Loads take 2 extra cycles to complete and 4 can be buffered at a time.
307
308 (define_function_unit "tsc701_load" 4 1
309   (and (eq_attr "cpu" "tsc701")
310     (eq_attr "type" "load,sload"))
311   3 1)
312
313 ;; Stores take 2(?) extra cycles to complete.
314 ;; It is desirable to not have any memory operation in the following 2 cycles.
315 ;; (??? or 2 memory ops in the case of std).
316
317 (define_function_unit "tsc701_store" 1 0
318   (and (eq_attr "cpu" "tsc701")
319     (eq_attr "type" "store"))
320   3 3
321   [(eq_attr "type" "load,sload,store")])
322
323 ;; The multiply unit has a latency of 5.
324 (define_function_unit "tsc701_mul" 1 0
325   (and (eq_attr "cpu" "tsc701")
326     (eq_attr "type" "imul"))
327   5 5)
328
329 ;; ----- The UltraSPARC-1 scheduling
330 ;; UltraSPARC has two integer units.  Shift instructions can only execute
331 ;; on IE0.  Condition code setting instructions, call, and jmpl (including
332 ;; the ret and retl pseudo-instructions) can only execute on IE1.
333 ;; Branch on register uses IE1, but branch on condition code does not.
334 ;; Conditional moves take 2 cycles.  No other instruction can issue in the
335 ;; same cycle as a conditional move.
336 ;; Multiply and divide take many cycles during which no other instructions
337 ;; can issue.
338 ;; Memory delivers its result in two cycles (except for signed loads,
339 ;; which take one cycle more).  One memory instruction can be issued per
340 ;; cycle.
341
342 (define_function_unit "memory" 1 0
343   (and (eq_attr "cpu" "ultrasparc")
344     (eq_attr "type" "load,fpload"))
345   2 1)
346
347 (define_function_unit "memory" 1 0
348   (and (eq_attr "cpu" "ultrasparc")
349     (eq_attr "type" "sload"))
350   3 1)
351
352 (define_function_unit "memory" 1 0
353   (and (eq_attr "cpu" "ultrasparc")
354     (eq_attr "type" "store,fpstore"))
355   1 1)
356
357 (define_function_unit "ieu" 1 0
358   (and (eq_attr "cpu" "ultrasparc")
359     (eq_attr "type" "ialu,shift,compare,cmove,call"))
360   1 1)
361
362 (define_function_unit "ieu_shift" 1 0
363   (and (eq_attr "cpu" "ultrasparc")
364     (eq_attr "type" "shift"))
365   1 1)
366
367 (define_function_unit "ieu_shift" 1 0
368   (and (eq_attr "cpu" "ultrasparc")
369     (eq_attr "type" "cmove"))
370   2 1)
371
372 ;; Timings; throughput/latency
373 ;; ?? FADD     1/3    add/sub, format conv, compar, abs, neg
374 ;; ?? FMUL     1/3
375 ;; ?? FDIVs    1/12
376 ;; ?? FDIVd    1/22
377 ;; ?? FSQRTs   1/12
378 ;; ?? FSQRTd   1/22
379
380 (define_function_unit "fadd" 1 0
381   (and (eq_attr "cpu" "ultrasparc")
382     (eq_attr "type" "fpmove"))
383   1 1)
384
385 (define_function_unit "fadd" 1 0
386   (and (eq_attr "cpu" "ultrasparc")
387     (eq_attr "type" "fpcmove"))
388   2 1)
389
390 (define_function_unit "fadd" 1 0
391   (and (eq_attr "cpu" "ultrasparc")
392     (eq_attr "type" "fp"))
393   4 1)
394
395 (define_function_unit "fadd" 1 0
396   (and (eq_attr "cpu" "ultrasparc")
397     (eq_attr "type" "fpcmp"))
398   2 1)
399
400 (define_function_unit "fmul" 1 0
401   (and (eq_attr "cpu" "ultrasparc")
402     (eq_attr "type" "fpmul"))
403   4 1)
404
405 (define_function_unit "fadd" 1 0
406   (and (eq_attr "cpu" "ultrasparc")
407     (eq_attr "type" "fpcmove"))
408   2 1)
409
410 (define_function_unit "fadd" 1 0
411   (and (eq_attr "cpu" "ultrasparc")
412     (eq_attr "type" "fpdivs"))
413   12 12)
414
415 (define_function_unit "fadd" 1 0
416   (and (eq_attr "cpu" "ultrasparc")
417     (eq_attr "type" "fpdivd"))
418   22 22)
419
420 (define_function_unit "fadd" 1 0
421   (and (eq_attr "cpu" "ultrasparc")
422     (eq_attr "type" "fpsqrt"))
423   12 12)
424 \f
425 ;; Compare instructions.
426 ;; This controls RTL generation and register allocation.
427
428 ;; We generate RTL for comparisons and branches by having the cmpxx 
429 ;; patterns store away the operands.  Then, the scc and bcc patterns
430 ;; emit RTL for both the compare and the branch.
431 ;;
432 ;; We do this because we want to generate different code for an sne and
433 ;; seq insn.  In those cases, if the second operand of the compare is not
434 ;; const0_rtx, we want to compute the xor of the two operands and test
435 ;; it against zero.
436 ;;
437 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
438 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
439 ;; insns that actually require more than one machine instruction.
440
441 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
442
443 (define_expand "cmpsi"
444   [(set (reg:CC 100)
445         (compare:CC (match_operand:SI 0 "register_operand" "")
446                     (match_operand:SI 1 "arith_operand" "")))]
447   ""
448   "
449 {
450   sparc_compare_op0 = operands[0];
451   sparc_compare_op1 = operands[1];
452   DONE;
453 }")
454
455 (define_expand "cmpdi"
456   [(set (reg:CCX 100)
457         (compare:CCX (match_operand:DI 0 "register_operand" "")
458                      (match_operand:DI 1 "arith_double_operand" "")))]
459   "TARGET_ARCH64"
460   "
461 {
462   sparc_compare_op0 = operands[0];
463   sparc_compare_op1 = operands[1];
464   DONE;
465 }")
466
467 (define_expand "cmpsf"
468   ;; The 96 here isn't ever used by anyone.
469   [(set (reg:CCFP 96)
470         (compare:CCFP (match_operand:SF 0 "register_operand" "")
471                       (match_operand:SF 1 "register_operand" "")))]
472   "TARGET_FPU"
473   "
474 {
475   sparc_compare_op0 = operands[0];
476   sparc_compare_op1 = operands[1];
477   DONE;
478 }")
479
480 (define_expand "cmpdf"
481   ;; The 96 here isn't ever used by anyone.
482   [(set (reg:CCFP 96)
483         (compare:CCFP (match_operand:DF 0 "register_operand" "")
484                       (match_operand:DF 1 "register_operand" "")))]
485   "TARGET_FPU"
486   "
487 {
488   sparc_compare_op0 = operands[0];
489   sparc_compare_op1 = operands[1];
490   DONE;
491 }")
492
493 (define_expand "cmptf"
494   ;; The 96 here isn't ever used by anyone.
495   [(set (reg:CCFP 96)
496         (compare:CCFP (match_operand:TF 0 "register_operand" "")
497                       (match_operand:TF 1 "register_operand" "")))]
498   "TARGET_FPU"
499   "
500 {
501   sparc_compare_op0 = operands[0];
502   sparc_compare_op1 = operands[1];
503   DONE;
504 }")
505
506 ;; Now the compare DEFINE_INSNs.
507
508 (define_insn "*cmpsi_insn"
509   [(set (reg:CC 100)
510         (compare:CC (match_operand:SI 0 "register_operand" "r")
511                     (match_operand:SI 1 "arith_operand" "rI")))]
512   ""
513   "cmp %0,%1"
514   [(set_attr "type" "compare")])
515
516 (define_insn "*cmpdi_sp64"
517   [(set (reg:CCX 100)
518         (compare:CCX (match_operand:DI 0 "register_operand" "r")
519                      (match_operand:DI 1 "arith_double_operand" "rHI")))]
520   "TARGET_ARCH64"
521   "cmp %0,%1"
522   [(set_attr "type" "compare")])
523
524 (define_insn "*cmpsf_fpe"
525   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
526         (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
527                        (match_operand:SF 2 "register_operand" "f")))]
528   "TARGET_FPU"
529   "*
530 {
531   if (TARGET_V9)
532     return \"fcmpes %0,%1,%2\";
533   return \"fcmpes %1,%2\";
534 }"
535   [(set_attr "type" "fpcmp")])
536
537 (define_insn "*cmpdf_fpe"
538   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
539         (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
540                        (match_operand:DF 2 "register_operand" "e")))]
541   "TARGET_FPU"
542   "*
543 {
544   if (TARGET_V9)
545     return \"fcmped %0,%1,%2\";
546   return \"fcmped %1,%2\";
547 }"
548   [(set_attr "type" "fpcmp")])
549
550 (define_insn "*cmptf_fpe"
551   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
552         (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
553                        (match_operand:TF 2 "register_operand" "e")))]
554   "TARGET_FPU && TARGET_HARD_QUAD"
555   "*
556 {
557   if (TARGET_V9)
558     return \"fcmpeq %0,%1,%2\";
559   return \"fcmpeq %1,%2\";
560 }"
561   [(set_attr "type" "fpcmp")])
562
563 (define_insn "*cmpsf_fp"
564   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
565         (compare:CCFP (match_operand:SF 1 "register_operand" "f")
566                       (match_operand:SF 2 "register_operand" "f")))]
567   "TARGET_FPU"
568   "*
569 {
570   if (TARGET_V9)
571     return \"fcmps %0,%1,%2\";
572   return \"fcmps %1,%2\";
573 }"
574   [(set_attr "type" "fpcmp")])
575
576 (define_insn "*cmpdf_fp"
577   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
578         (compare:CCFP (match_operand:DF 1 "register_operand" "e")
579                       (match_operand:DF 2 "register_operand" "e")))]
580   "TARGET_FPU"
581   "*
582 {
583   if (TARGET_V9)
584     return \"fcmpd %0,%1,%2\";
585   return \"fcmpd %1,%2\";
586 }"
587   [(set_attr "type" "fpcmp")])
588
589 (define_insn "*cmptf_fp"
590   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
591         (compare:CCFP (match_operand:TF 1 "register_operand" "e")
592                       (match_operand:TF 2 "register_operand" "e")))]
593   "TARGET_FPU && TARGET_HARD_QUAD"
594   "*
595 {
596   if (TARGET_V9)
597     return \"fcmpq %0,%1,%2\";
598   return \"fcmpq %1,%2\";
599 }"
600   [(set_attr "type" "fpcmp")])
601 \f
602 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
603 ;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
604 ;; the same code as v8 (the addx/subx method has more applications).  The
605 ;; exception to this is "reg != 0" which can be done in one instruction on v9
606 ;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
607 ;; branches.
608
609 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
610 ;; generate addcc/subcc instructions.
611
612 (define_expand "seqsi_special"
613   [(set (match_dup 3)
614         (xor:SI (match_operand:SI 1 "register_operand" "")
615                 (match_operand:SI 2 "register_operand" "")))
616    (parallel [(set (match_operand:SI 0 "register_operand" "")
617                    (eq:SI (match_dup 3) (const_int 0)))
618               (clobber (reg:CC 100))])]
619   "! TARGET_LIVE_G0"
620   "{ operands[3] = gen_reg_rtx (SImode); }")
621
622 (define_expand "seqdi_special"
623   [(set (match_dup 3)
624         (xor:DI (match_operand:DI 1 "register_operand" "")
625                 (match_operand:DI 2 "register_operand" "")))
626    (set (match_operand:DI 0 "register_operand" "")
627         (eq:DI (match_dup 3) (const_int 0)))]
628   "TARGET_ARCH64"
629   "{ operands[3] = gen_reg_rtx (DImode); }")
630
631 (define_expand "snesi_special"
632   [(set (match_dup 3)
633         (xor:SI (match_operand:SI 1 "register_operand" "")
634                 (match_operand:SI 2 "register_operand" "")))
635    (parallel [(set (match_operand:SI 0 "register_operand" "")
636                    (ne:SI (match_dup 3) (const_int 0)))
637               (clobber (reg:CC 100))])]
638   "! TARGET_LIVE_G0"
639   "{ operands[3] = gen_reg_rtx (SImode); }")
640
641 (define_expand "snedi_special"
642   [(set (match_dup 3)
643         (xor:DI (match_operand:DI 1 "register_operand" "")
644                 (match_operand:DI 2 "register_operand" "")))
645    (set (match_operand:DI 0 "register_operand" "")
646         (ne:DI (match_dup 3) (const_int 0)))]
647   "TARGET_ARCH64"
648   "{ operands[3] = gen_reg_rtx (DImode); }")
649
650 (define_expand "seqdi_special_trunc"
651   [(set (match_dup 3)
652         (xor:DI (match_operand:DI 1 "register_operand" "")
653                 (match_operand:DI 2 "register_operand" "")))
654    (set (match_operand:SI 0 "register_operand" "")
655         (eq:DI (match_dup 3) (const_int 0)))]
656   "TARGET_ARCH64"
657   "{ operands[3] = gen_reg_rtx (DImode); }")
658
659 (define_expand "snedi_special_trunc"
660   [(set (match_dup 3)
661         (xor:DI (match_operand:DI 1 "register_operand" "")
662                 (match_operand:DI 2 "register_operand" "")))
663    (set (match_operand:SI 0 "register_operand" "")
664         (ne:DI (match_dup 3) (const_int 0)))]
665   "TARGET_ARCH64"
666   "{ operands[3] = gen_reg_rtx (DImode); }")
667
668 (define_expand "seqsi_special_extend"
669   [(set (match_dup 3)
670         (xor:SI (match_operand:SI 1 "register_operand" "")
671                 (match_operand:SI 2 "register_operand" "")))
672    (parallel [(set (match_operand:DI 0 "register_operand" "")
673                    (eq:SI (match_dup 3) (const_int 0)))
674               (clobber (reg:CC 100))])]
675   "TARGET_ARCH64"
676   "{ operands[3] = gen_reg_rtx (SImode); }")
677
678 (define_expand "snesi_special_extend"
679   [(set (match_dup 3)
680         (xor:SI (match_operand:SI 1 "register_operand" "")
681                 (match_operand:SI 2 "register_operand" "")))
682    (parallel [(set (match_operand:DI 0 "register_operand" "")
683                    (ne:SI (match_dup 3) (const_int 0)))
684               (clobber (reg:CC 100))])]
685   "TARGET_ARCH64"
686   "{ operands[3] = gen_reg_rtx (SImode); }")
687
688 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
689 ;; However, the code handles both SImode and DImode.
690 (define_expand "seq"
691   [(set (match_operand:SI 0 "intreg_operand" "")
692         (eq:SI (match_dup 1) (const_int 0)))]
693   "! TARGET_LIVE_G0"
694   "
695 {
696   if (GET_MODE (sparc_compare_op0) == SImode)
697     {
698       rtx pat;
699
700       if (GET_MODE (operands[0]) == SImode)
701         pat = gen_seqsi_special (operands[0], sparc_compare_op0,
702                                  sparc_compare_op1);
703       else if (! TARGET_ARCH64)
704         FAIL;
705       else
706         pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
707                                         sparc_compare_op1);
708       emit_insn (pat);
709       DONE;
710     }
711   else if (GET_MODE (sparc_compare_op0) == DImode)
712     {
713       rtx pat;
714
715       if (! TARGET_ARCH64)
716         FAIL;
717       else if (GET_MODE (operands[0]) == SImode)
718         pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
719                                        sparc_compare_op1);
720       else
721         pat = gen_seqdi_special (operands[0], sparc_compare_op0,
722                                  sparc_compare_op1);
723       emit_insn (pat);
724       DONE;
725     }
726   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
727     {
728       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
729       emit_insn (gen_sne (operands[0]));
730       DONE;
731     }      
732   else if (TARGET_V9)
733     {
734       if (gen_v9_scc (EQ, operands))
735         DONE;
736       /* fall through */
737     }
738   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
739 }")
740
741 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
742 ;; However, the code handles both SImode and DImode.
743 (define_expand "sne"
744   [(set (match_operand:SI 0 "intreg_operand" "")
745         (ne:SI (match_dup 1) (const_int 0)))]
746   "! TARGET_LIVE_G0"
747   "
748 {
749   if (GET_MODE (sparc_compare_op0) == SImode)
750     {
751       rtx pat;
752
753       if (GET_MODE (operands[0]) == SImode)
754         pat = gen_snesi_special (operands[0], sparc_compare_op0,
755                                  sparc_compare_op1);
756       else if (! TARGET_ARCH64)
757         FAIL;
758       else
759         pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
760                                         sparc_compare_op1);
761       emit_insn (pat);
762       DONE;
763     }
764   else if (GET_MODE (sparc_compare_op0) == DImode)
765     {
766       rtx pat;
767
768       if (! TARGET_ARCH64)
769         FAIL;
770       else if (GET_MODE (operands[0]) == SImode)
771         pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
772                                        sparc_compare_op1);
773       else
774         pat = gen_snedi_special (operands[0], sparc_compare_op0,
775                                  sparc_compare_op1);
776       emit_insn (pat);
777       DONE;
778     }
779   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
780     {
781       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
782       emit_insn (gen_sne (operands[0]));
783       DONE;
784     }      
785   else if (TARGET_V9)
786     {
787       if (gen_v9_scc (NE, operands))
788         DONE;
789       /* fall through */
790     }
791   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
792 }")
793
794 (define_expand "sgt"
795   [(set (match_operand:SI 0 "intreg_operand" "")
796         (gt:SI (match_dup 1) (const_int 0)))]
797   "! TARGET_LIVE_G0"
798   "
799 {
800   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
801     {
802       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
803       emit_insn (gen_sne (operands[0]));
804       DONE;
805     }
806   else if (TARGET_V9)
807     {
808       if (gen_v9_scc (GT, operands))
809         DONE;
810       /* fall through */
811     }
812   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
813 }")
814
815 (define_expand "slt"
816   [(set (match_operand:SI 0 "intreg_operand" "")
817         (lt:SI (match_dup 1) (const_int 0)))]
818   "! TARGET_LIVE_G0"
819   "
820 {
821   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
822     {
823       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
824       emit_insn (gen_sne (operands[0]));
825       DONE;
826     }
827   else if (TARGET_V9)
828     {
829       if (gen_v9_scc (LT, operands))
830         DONE;
831       /* fall through */
832     }
833   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
834 }")
835
836 (define_expand "sge"
837   [(set (match_operand:SI 0 "intreg_operand" "")
838         (ge:SI (match_dup 1) (const_int 0)))]
839   "! TARGET_LIVE_G0"
840   "
841 {
842   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
843     {
844       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
845       emit_insn (gen_sne (operands[0]));
846       DONE;
847     }
848   else if (TARGET_V9)
849     {
850       if (gen_v9_scc (GE, operands))
851         DONE;
852       /* fall through */
853     }
854   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
855 }")
856
857 (define_expand "sle"
858   [(set (match_operand:SI 0 "intreg_operand" "")
859         (le:SI (match_dup 1) (const_int 0)))]
860   "! TARGET_LIVE_G0"
861   "
862 {
863   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
864     {
865       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
866       emit_insn (gen_sne (operands[0]));
867       DONE;
868     }
869   else if (TARGET_V9)
870     {
871       if (gen_v9_scc (LE, operands))
872         DONE;
873       /* fall through */
874     }
875   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
876 }")
877
878 (define_expand "sgtu"
879   [(set (match_operand:SI 0 "intreg_operand" "")
880         (gtu:SI (match_dup 1) (const_int 0)))]
881   "! TARGET_LIVE_G0"
882   "
883 {
884   if (! TARGET_V9)
885     {
886       rtx tem;
887
888       /* We can do ltu easily, so if both operands are registers, swap them and
889          do a LTU.  */
890       if ((GET_CODE (sparc_compare_op0) == REG
891            || GET_CODE (sparc_compare_op0) == SUBREG)
892           && (GET_CODE (sparc_compare_op1) == REG
893               || GET_CODE (sparc_compare_op1) == SUBREG))
894         {
895           tem = sparc_compare_op0;
896           sparc_compare_op0 = sparc_compare_op1;
897           sparc_compare_op1 = tem;
898           emit_insn (gen_sltu (operands[0]));
899           DONE;
900         }
901     }
902   else
903     {
904       if (gen_v9_scc (GTU, operands))
905         DONE;
906     }
907   operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
908 }")
909
910 (define_expand "sltu"
911   [(set (match_operand:SI 0 "intreg_operand" "")
912         (ltu:SI (match_dup 1) (const_int 0)))]
913   "! TARGET_LIVE_G0"
914   "
915 {
916   if (TARGET_V9)
917     {
918       if (gen_v9_scc (LTU, operands))
919         DONE;
920     }
921   operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
922 }")
923
924 (define_expand "sgeu"
925   [(set (match_operand:SI 0 "intreg_operand" "")
926         (geu:SI (match_dup 1) (const_int 0)))]
927   "! TARGET_LIVE_G0"
928   "
929 {
930   if (TARGET_V9)
931     {
932       if (gen_v9_scc (GEU, operands))
933         DONE;
934     }
935   operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
936 }")
937
938 (define_expand "sleu"
939   [(set (match_operand:SI 0 "intreg_operand" "")
940         (leu:SI (match_dup 1) (const_int 0)))]
941   "! TARGET_LIVE_G0"
942   "
943 {
944   if (! TARGET_V9)
945     {
946       rtx tem;
947
948       /* We can do geu easily, so if both operands are registers, swap them and
949          do a GEU.  */
950       if ((GET_CODE (sparc_compare_op0) == REG
951            || GET_CODE (sparc_compare_op0) == SUBREG)
952           && (GET_CODE (sparc_compare_op1) == REG
953               || GET_CODE (sparc_compare_op1) == SUBREG))
954         {
955           tem = sparc_compare_op0;
956           sparc_compare_op0 = sparc_compare_op1;
957           sparc_compare_op1 = tem;
958           emit_insn (gen_sgeu (operands[0]));
959           DONE;
960         }
961     }
962   else
963     {
964       if (gen_v9_scc (LEU, operands))
965         DONE;
966     }
967   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
968 }")
969
970 ;; Now the DEFINE_INSNs for the scc cases.
971
972 ;; The SEQ and SNE patterns are special because they can be done
973 ;; without any branching and do not involve a COMPARE.
974
975 (define_insn "*snesi_zero"
976   [(set (match_operand:SI 0 "register_operand" "=r")
977         (ne:SI (match_operand:SI 1 "register_operand" "r")
978                (const_int 0)))
979    (clobber (reg:CC 100))]
980   "! TARGET_LIVE_G0"
981   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
982   [(set_attr "type" "unary")
983    (set_attr "length" "2")])
984
985 (define_insn "*neg_snesi_zero"
986   [(set (match_operand:SI 0 "register_operand" "=r")
987         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
988                        (const_int 0))))
989    (clobber (reg:CC 100))]
990   "! TARGET_LIVE_G0"
991   "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
992   [(set_attr "type" "unary")
993    (set_attr "length" "2")])
994
995 (define_insn "*snesi_zero_extend"
996   [(set (match_operand:DI 0 "register_operand" "=r")
997         (ne:SI (match_operand:SI 1 "register_operand" "r")
998                (const_int 0)))
999    (clobber (reg:CC 100))]
1000   "TARGET_ARCH64"
1001   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
1002   [(set_attr "type" "unary")
1003    (set_attr "length" "2")])
1004
1005 (define_insn "*snedi_zero"
1006   [(set (match_operand:DI 0 "register_operand" "=&r")
1007         (ne:DI (match_operand:DI 1 "register_operand" "r")
1008                (const_int 0)))]
1009   "TARGET_ARCH64"
1010   "mov 0,%0\;movrnz %1,1,%0"
1011   [(set_attr "type" "unary")
1012    (set_attr "length" "2")])
1013
1014 (define_insn "*neg_snedi_zero"
1015   [(set (match_operand:DI 0 "register_operand" "=&r")
1016         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
1017                        (const_int 0))))]
1018   "TARGET_ARCH64"
1019   "mov 0,%0\;movrnz %1,-1,%0"
1020   [(set_attr "type" "unary")
1021    (set_attr "length" "2")])
1022
1023 (define_insn "*snedi_zero_trunc"
1024   [(set (match_operand:SI 0 "register_operand" "=&r")
1025         (ne:DI (match_operand:DI 1 "register_operand" "r")
1026                (const_int 0)))]
1027   "TARGET_ARCH64"
1028   "mov 0,%0\;movrnz %1,1,%0"
1029   [(set_attr "type" "unary")
1030    (set_attr "length" "2")])
1031
1032 (define_insn "*seqsi_zero"
1033   [(set (match_operand:SI 0 "register_operand" "=r")
1034         (eq:SI (match_operand:SI 1 "register_operand" "r")
1035                (const_int 0)))
1036    (clobber (reg:CC 100))]
1037   "! TARGET_LIVE_G0"
1038   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
1039   [(set_attr "type" "unary")
1040    (set_attr "length" "2")])
1041
1042 (define_insn "*neg_seqsi_zero"
1043   [(set (match_operand:SI 0 "register_operand" "=r")
1044         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1045                        (const_int 0))))
1046    (clobber (reg:CC 100))]
1047   "! TARGET_LIVE_G0"
1048   "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
1049   [(set_attr "type" "unary")
1050    (set_attr "length" "2")])
1051
1052 (define_insn "*seqsi_zero_extend"
1053   [(set (match_operand:DI 0 "register_operand" "=r")
1054         (eq:SI (match_operand:SI 1 "register_operand" "r")
1055                (const_int 0)))
1056    (clobber (reg:CC 100))]
1057   "TARGET_ARCH64"
1058   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
1059   [(set_attr "type" "unary")
1060    (set_attr "length" "2")])
1061
1062 (define_insn "*seqdi_zero"
1063   [(set (match_operand:DI 0 "register_operand" "=&r")
1064         (eq:DI (match_operand:DI 1 "register_operand" "r")
1065                (const_int 0)))]
1066   "TARGET_ARCH64"
1067   "mov 0,%0\;movrz %1,1,%0"
1068   [(set_attr "type" "unary")
1069    (set_attr "length" "2")])
1070
1071 (define_insn "*neg_seqdi_zero"
1072   [(set (match_operand:DI 0 "register_operand" "=&r")
1073         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
1074                        (const_int 0))))]
1075   "TARGET_ARCH64"
1076   "mov 0,%0\;movrz %1,-1,%0"
1077   [(set_attr "type" "unary")
1078    (set_attr "length" "2")]) 
1079
1080 (define_insn "*seqdi_zero_trunc"
1081   [(set (match_operand:SI 0 "register_operand" "=&r")
1082         (eq:DI (match_operand:DI 1 "register_operand" "r")
1083                (const_int 0)))]
1084   "TARGET_ARCH64"
1085   "mov 0,%0\;movrz %1,1,%0"
1086   [(set_attr "type" "unary")
1087    (set_attr "length" "2")])
1088
1089 ;; We can also do (x + (i == 0)) and related, so put them in.
1090 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1091 ;; versions for v9.
1092
1093 (define_insn "*x_plus_i_ne_0"
1094   [(set (match_operand:SI 0 "register_operand" "=r")
1095         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
1096                         (const_int 0))
1097                  (match_operand:SI 2 "register_operand" "r")))
1098    (clobber (reg:CC 100))]
1099   "! TARGET_LIVE_G0"
1100   "subcc %%g0,%1,%%g0\;addx %2,0,%0"
1101   [(set_attr "length" "2")])
1102
1103 (define_insn "*x_minus_i_ne_0"
1104   [(set (match_operand:SI 0 "register_operand" "=r")
1105         (minus:SI (match_operand:SI 2 "register_operand" "r")
1106                   (ne:SI (match_operand:SI 1 "register_operand" "r")
1107                          (const_int 0))))
1108    (clobber (reg:CC 100))]
1109   "! TARGET_LIVE_G0"
1110   "subcc %%g0,%1,%%g0\;subx %2,0,%0"
1111   [(set_attr "length" "2")])
1112
1113 (define_insn "*x_plus_i_eq_0"
1114   [(set (match_operand:SI 0 "register_operand" "=r")
1115         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1116                         (const_int 0))
1117                  (match_operand:SI 2 "register_operand" "r")))
1118    (clobber (reg:CC 100))]
1119   "! TARGET_LIVE_G0"
1120   "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
1121   [(set_attr "length" "2")])
1122
1123 (define_insn "*x_minus_i_eq_0"
1124   [(set (match_operand:SI 0 "register_operand" "=r")
1125         (minus:SI (match_operand:SI 2 "register_operand" "r")
1126                   (eq:SI (match_operand:SI 1 "register_operand" "r")
1127                          (const_int 0))))
1128    (clobber (reg:CC 100))]
1129   "! TARGET_LIVE_G0"
1130   "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
1131   [(set_attr "length" "2")])
1132
1133 ;; We can also do GEU and LTU directly, but these operate after a compare.
1134 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1135 ;; versions for v9.
1136
1137 (define_insn "*sltu_insn"
1138   [(set (match_operand:SI 0 "register_operand" "=r")
1139         (ltu:SI (reg:CC 100) (const_int 0)))]
1140   "! TARGET_LIVE_G0"
1141   "addx %%g0,0,%0"
1142   [(set_attr "type" "misc")])
1143
1144 (define_insn "*neg_sltu_insn"
1145   [(set (match_operand:SI 0 "register_operand" "=r")
1146         (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1147   "! TARGET_LIVE_G0"
1148   "subx %%g0,0,%0"
1149   [(set_attr "type" "misc")])
1150
1151 ;; ??? Combine should canonicalize these next two to the same pattern.
1152 (define_insn "*neg_sltu_minus_x"
1153   [(set (match_operand:SI 0 "register_operand" "=r")
1154         (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1155                   (match_operand:SI 1 "arith_operand" "rI")))]
1156   "! TARGET_LIVE_G0"
1157   "subx %%g0,%1,%0"
1158   [(set_attr "type" "unary")])
1159
1160 (define_insn "*neg_sltu_plus_x"
1161   [(set (match_operand:SI 0 "register_operand" "=r")
1162         (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1163                          (match_operand:SI 1 "arith_operand" "rI"))))]
1164   "! TARGET_LIVE_G0"
1165   "subx %%g0,%1,%0"
1166   [(set_attr "type" "unary")])
1167
1168 (define_insn "*sgeu_insn"
1169   [(set (match_operand:SI 0 "register_operand" "=r")
1170         (geu:SI (reg:CC 100) (const_int 0)))]
1171   "! TARGET_LIVE_G0"
1172   "subx %%g0,-1,%0"
1173   [(set_attr "type" "misc")])
1174
1175 (define_insn "*neg_sgeu_insn"
1176   [(set (match_operand:SI 0 "register_operand" "=r")
1177         (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1178   "! TARGET_LIVE_G0"
1179   "addx %%g0,-1,%0"
1180   [(set_attr "type" "misc")])
1181
1182 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1183 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1184 ;; versions for v9.
1185
1186 (define_insn "*sltu_plus_x"
1187   [(set (match_operand:SI 0 "register_operand" "=r")
1188         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1189                  (match_operand:SI 1 "arith_operand" "rI")))]
1190   "! TARGET_LIVE_G0"
1191   "addx %%g0,%1,%0"
1192   [(set_attr "type" "unary")])
1193
1194 (define_insn "*sltu_plus_x_plus_y"
1195   [(set (match_operand:SI 0 "register_operand" "=r")
1196         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1197                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1198                           (match_operand:SI 2 "arith_operand" "rI"))))]
1199   ""
1200   "addx %1,%2,%0")
1201
1202 (define_insn "*x_minus_sltu"
1203   [(set (match_operand:SI 0 "register_operand" "=r")
1204         (minus:SI (match_operand:SI 1 "register_operand" "r")
1205                   (ltu:SI (reg:CC 100) (const_int 0))))]
1206   ""
1207   "subx %1,0,%0"
1208   [(set_attr "type" "unary")])
1209
1210 ;; ??? Combine should canonicalize these next two to the same pattern.
1211 (define_insn "*x_minus_y_minus_sltu"
1212   [(set (match_operand:SI 0 "register_operand" "=r")
1213         (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
1214                             (match_operand:SI 2 "arith_operand" "rI"))
1215                   (ltu:SI (reg:CC 100) (const_int 0))))]
1216   ""
1217   "subx %1,%2,%0")
1218
1219 (define_insn "*x_minus_sltu_plus_y"
1220   [(set (match_operand:SI 0 "register_operand" "=r")
1221         (minus:SI (match_operand:SI 1 "register_operand" "r")
1222                   (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1223                            (match_operand:SI 2 "arith_operand" "rI"))))]
1224   ""
1225   "subx %1,%2,%0")
1226
1227 (define_insn "*sgeu_plus_x"
1228   [(set (match_operand:SI 0 "register_operand" "=r")
1229         (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1230                  (match_operand:SI 1 "register_operand" "r")))]
1231   ""
1232   "subx %1,-1,%0"
1233   [(set_attr "type" "unary")])
1234
1235 (define_insn "*x_minus_sgeu"
1236   [(set (match_operand:SI 0 "register_operand" "=r")
1237         (minus:SI (match_operand:SI 1 "register_operand" "r")
1238                   (geu:SI (reg:CC 100) (const_int 0))))]
1239   ""
1240   "addx %1,-1,%0"
1241   [(set_attr "type" "unary")])
1242
1243 ;; Now we have the generic scc insns.
1244 ;; !v9: These will be done using a jump.
1245 ;; v9: Use conditional moves which are defined elsewhere.
1246 ;; We have to exclude the cases above, since we will not want combine to
1247 ;; turn something that does not require a jump into something that does.
1248
1249 (define_insn "*scc_si"
1250   [(set (match_operand:SI 0 "register_operand" "=r")
1251         (match_operator:SI 2 "noov_compare_op"
1252                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1253                             (const_int 0)]))]
1254   ""
1255   "* return output_scc_insn (operands, insn); "
1256   [(set_attr "type" "multi")
1257    (set_attr "length" "3")])
1258
1259 (define_insn "*scc_di"
1260   [(set (match_operand:DI 0 "register_operand" "=r")
1261         (match_operator:DI 2 "noov_compare_op"
1262                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1263                             (const_int 0)]))]
1264   "TARGET_ARCH64"
1265   "* return output_scc_insn (operands, insn); "
1266   [(set_attr "type" "multi")
1267    (set_attr "length" "3")])
1268 \f
1269 ;; These control RTL generation for conditional jump insns
1270
1271 ;; The quad-word fp compare library routines all return nonzero to indicate
1272 ;; true, which is different from the equivalent libgcc routines, so we must
1273 ;; handle them specially here.
1274
1275 (define_expand "beq"
1276   [(set (pc)
1277         (if_then_else (eq (match_dup 1) (const_int 0))
1278                       (label_ref (match_operand 0 "" ""))
1279                       (pc)))]
1280   ""
1281   "
1282 {
1283   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1284       && GET_CODE (sparc_compare_op0) == REG
1285       && GET_MODE (sparc_compare_op0) == DImode)
1286     {
1287       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1288       DONE;
1289     }
1290   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1291     {
1292       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1293       emit_jump_insn (gen_bne (operands[0]));
1294       DONE;
1295     }      
1296   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1297 }")
1298
1299 (define_expand "bne"
1300   [(set (pc)
1301         (if_then_else (ne (match_dup 1) (const_int 0))
1302                       (label_ref (match_operand 0 "" ""))
1303                       (pc)))]
1304   ""
1305   "
1306 {
1307   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1308       && GET_CODE (sparc_compare_op0) == REG
1309       && GET_MODE (sparc_compare_op0) == DImode)
1310     {
1311       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1312       DONE;
1313     }
1314   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1315     {
1316       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1317       emit_jump_insn (gen_bne (operands[0]));
1318       DONE;
1319     }      
1320   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1321 }")
1322
1323 (define_expand "bgt"
1324   [(set (pc)
1325         (if_then_else (gt (match_dup 1) (const_int 0))
1326                       (label_ref (match_operand 0 "" ""))
1327                       (pc)))]
1328   ""
1329   "
1330 {
1331   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1332       && GET_CODE (sparc_compare_op0) == REG
1333       && GET_MODE (sparc_compare_op0) == DImode)
1334     {
1335       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1336       DONE;
1337     }
1338   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1339     {
1340       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1341       emit_jump_insn (gen_bne (operands[0]));
1342       DONE;
1343     }      
1344   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1345 }")
1346
1347 (define_expand "bgtu"
1348   [(set (pc)
1349         (if_then_else (gtu (match_dup 1) (const_int 0))
1350                       (label_ref (match_operand 0 "" ""))
1351                       (pc)))]
1352   ""
1353   "
1354 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1355 }")
1356
1357 (define_expand "blt"
1358   [(set (pc)
1359         (if_then_else (lt (match_dup 1) (const_int 0))
1360                       (label_ref (match_operand 0 "" ""))
1361                       (pc)))]
1362   ""
1363   "
1364 {
1365   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1366       && GET_CODE (sparc_compare_op0) == REG
1367       && GET_MODE (sparc_compare_op0) == DImode)
1368     {
1369       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1370       DONE;
1371     }
1372   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1373     {
1374       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1375       emit_jump_insn (gen_bne (operands[0]));
1376       DONE;
1377     }      
1378   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1379 }")
1380
1381 (define_expand "bltu"
1382   [(set (pc)
1383         (if_then_else (ltu (match_dup 1) (const_int 0))
1384                       (label_ref (match_operand 0 "" ""))
1385                       (pc)))]
1386   ""
1387   "
1388 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1389 }")
1390
1391 (define_expand "bge"
1392   [(set (pc)
1393         (if_then_else (ge (match_dup 1) (const_int 0))
1394                       (label_ref (match_operand 0 "" ""))
1395                       (pc)))]
1396   ""
1397   "
1398 {
1399   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1400       && GET_CODE (sparc_compare_op0) == REG
1401       && GET_MODE (sparc_compare_op0) == DImode)
1402     {
1403       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1404       DONE;
1405     }
1406   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1407     {
1408       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1409       emit_jump_insn (gen_bne (operands[0]));
1410       DONE;
1411     }      
1412   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1413 }")
1414
1415 (define_expand "bgeu"
1416   [(set (pc)
1417         (if_then_else (geu (match_dup 1) (const_int 0))
1418                       (label_ref (match_operand 0 "" ""))
1419                       (pc)))]
1420   ""
1421   "
1422 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1423 }")
1424
1425 (define_expand "ble"
1426   [(set (pc)
1427         (if_then_else (le (match_dup 1) (const_int 0))
1428                       (label_ref (match_operand 0 "" ""))
1429                       (pc)))]
1430   ""
1431   "
1432 {
1433   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1434       && GET_CODE (sparc_compare_op0) == REG
1435       && GET_MODE (sparc_compare_op0) == DImode)
1436     {
1437       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1438       DONE;
1439     }
1440   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1441     {
1442       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1443       emit_jump_insn (gen_bne (operands[0]));
1444       DONE;
1445     }      
1446   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1447 }")
1448
1449 (define_expand "bleu"
1450   [(set (pc)
1451         (if_then_else (leu (match_dup 1) (const_int 0))
1452                       (label_ref (match_operand 0 "" ""))
1453                       (pc)))]
1454   ""
1455   "
1456 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1457 }")
1458 \f
1459 ;; Now match both normal and inverted jump.
1460
1461 (define_insn "*normal_branch"
1462   [(set (pc)
1463         (if_then_else (match_operator 0 "noov_compare_op"
1464                                       [(reg 100) (const_int 0)])
1465                       (label_ref (match_operand 1 "" ""))
1466                       (pc)))]
1467   ""
1468   "*
1469 {
1470   return output_cbranch (operands[0], 1, 0,
1471                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1472                          ! final_sequence);
1473 }"
1474   [(set_attr "type" "branch")])
1475
1476 (define_insn "*inverted_branch"
1477   [(set (pc)
1478         (if_then_else (match_operator 0 "noov_compare_op"
1479                                       [(reg 100) (const_int 0)])
1480                       (pc)
1481                       (label_ref (match_operand 1 "" ""))))]
1482   ""
1483   "*
1484 {
1485   return output_cbranch (operands[0], 1, 1,
1486                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1487                          ! final_sequence);
1488 }"
1489   [(set_attr "type" "branch")])
1490
1491 (define_insn "*normal_fp_branch"
1492   [(set (pc)
1493         (if_then_else (match_operator 1 "comparison_operator"
1494                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1495                                        (const_int 0)])
1496                       (label_ref (match_operand 2 "" ""))
1497                       (pc)))]
1498   ""
1499   "*
1500 {
1501   return output_cbranch (operands[1], 2, 0,
1502                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1503                          ! final_sequence);
1504 }"
1505   [(set_attr "type" "branch")])
1506
1507 (define_insn "*inverted_fp_branch"
1508   [(set (pc)
1509         (if_then_else (match_operator 1 "comparison_operator"
1510                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1511                                        (const_int 0)])
1512                       (pc)
1513                       (label_ref (match_operand 2 "" ""))))]
1514   ""
1515   "*
1516 {
1517   return output_cbranch (operands[1], 2, 1,
1518                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1519                          ! final_sequence);
1520 }"
1521   [(set_attr "type" "branch")])
1522
1523 (define_insn "*normal_fpe_branch"
1524   [(set (pc)
1525         (if_then_else (match_operator 1 "comparison_operator"
1526                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1527                                        (const_int 0)])
1528                       (label_ref (match_operand 2 "" ""))
1529                       (pc)))]
1530   ""
1531   "*
1532 {
1533   return output_cbranch (operands[1], 2, 0,
1534                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1535                          ! final_sequence);
1536 }"
1537   [(set_attr "type" "branch")])
1538
1539 (define_insn "*inverted_fpe_branch"
1540   [(set (pc)
1541         (if_then_else (match_operator 1 "comparison_operator"
1542                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1543                                        (const_int 0)])
1544                       (pc)
1545                       (label_ref (match_operand 2 "" ""))))]
1546   ""
1547   "*
1548 {
1549   return output_cbranch (operands[1], 2, 1,
1550                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1551                          ! final_sequence);
1552 }"
1553   [(set_attr "type" "branch")])
1554
1555 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
1556 ;; in the architecture.
1557
1558 ;; There are no 32 bit brreg insns.
1559
1560 (define_insn "*normal_int_branch_sp64"
1561   [(set (pc)
1562         (if_then_else (match_operator 0 "v9_regcmp_op"
1563                                       [(match_operand:DI 1 "register_operand" "r")
1564                                        (const_int 0)])
1565                       (label_ref (match_operand 2 "" ""))
1566                       (pc)))]
1567   "TARGET_ARCH64"
1568   "*
1569 {
1570   return output_v9branch (operands[0], 1, 2, 0,
1571                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1572                           ! final_sequence);
1573 }"
1574   [(set_attr "type" "branch")])
1575
1576 (define_insn "*inverted_int_branch_sp64"
1577   [(set (pc)
1578         (if_then_else (match_operator 0 "v9_regcmp_op"
1579                                       [(match_operand:DI 1 "register_operand" "r")
1580                                        (const_int 0)])
1581                       (pc)
1582                       (label_ref (match_operand 2 "" ""))))]
1583   "TARGET_ARCH64"
1584   "*
1585 {
1586   return output_v9branch (operands[0], 1, 2, 1,
1587                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1588                           ! final_sequence);
1589 }"
1590   [(set_attr "type" "branch")])
1591 \f
1592 ;; Esoteric move insns (lo_sum, high, pic).
1593
1594 (define_insn "*lo_sum_si"
1595   [(set (match_operand:SI 0 "register_operand" "=r")
1596         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1597                    (match_operand:SI 2 "immediate_operand" "in")))]
1598   ""
1599   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1600   ;; so we can compare the old compiler with the new.
1601   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1602   ;; Need to set length for this arith insn because operand2
1603   ;; is not an "arith_operand".
1604   [(set_attr "length" "1")])
1605
1606 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1607 ;; confuse them with real addresses.
1608 (define_insn "pic_lo_sum_si"
1609   [(set (match_operand:SI 0 "register_operand" "=r")
1610         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1611                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
1612   "flag_pic"
1613   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1614   ;; so we can compare the old compiler with the new.
1615   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1616   ;; Need to set length for this arith insn because operand2
1617   ;; is not an "arith_operand".
1618   [(set_attr "length" "1")])
1619
1620 ;; The PIC version of sethi must appear before the non-pic case so that
1621 ;; the unspec will not be matched as part of the operand.
1622 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1623 ;; confuse them with real addresses.
1624 (define_insn "pic_sethi_si"
1625   [(set (match_operand:SI 0 "register_operand" "=r")
1626         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1627   "flag_pic && check_pic (1)"
1628   "sethi %%hi(%a1),%0"
1629   [(set_attr "type" "move")
1630    (set_attr "length" "1")])
1631
1632 (define_insn "pic_lo_sum_di"
1633   [(set (match_operand:DI 0 "register_operand" "=r")
1634         (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
1635                    (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
1636   "TARGET_ARCH64 && flag_pic"
1637   "add %1,%%lo(%a2),%0"
1638   [(set_attr "length" "1")])
1639
1640 (define_insn "pic_sethi_di"
1641   [(set (match_operand:DI 0 "register_operand" "=r")
1642         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1643   "TARGET_ARCH64 && flag_pic && check_pic (1)"
1644   "sethi %%hi(%a1),%0"
1645   [(set_attr "type" "move")
1646    (set_attr "length" "1")])
1647
1648 (define_insn "get_pc_via_call"
1649   [(set (pc) (label_ref (match_operand 0 "" "")))
1650    (set (reg:SI 15) (label_ref (match_operand 1 "" "")))]
1651   ""
1652   "call %l0%#"
1653   [(set_attr "type" "uncond_branch")])
1654
1655 (define_insn "get_pc_via_rdpc"
1656   [(set (match_operand:DI 0 "register_operand" "=r") (pc))]
1657   "TARGET_V9"
1658   "rd %%pc,%0"
1659   [(set_attr "type" "move")])
1660
1661 ;; Special pic pattern, for loading the address of a label into a register.
1662 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
1663 ;; there.  The pic tablejump pattern also uses this.
1664
1665 (define_insn "move_pic_label_si"
1666   [(set (match_operand:SI 0 "register_operand" "=r")
1667         ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
1668         ; loses the volatil and other flags of the original label_ref.
1669         (match_operand:SI 1 "label_ref_operand" ""))
1670    (set (reg:SI 15) (pc))]
1671   "flag_pic"
1672   "*
1673 {
1674   if (get_attr_length (insn) == 2)
1675     return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
1676   else
1677     return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
1678 }"
1679   [(set_attr "type" "multi")
1680    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1681    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1682                                            (const_int 960))
1683                                       (const_int 2)
1684                                       (const_int 4)))])
1685
1686 ;; Special sparc64 pattern for loading the address of a label into a register.
1687 ;; The pic and non-pic cases are the same since it's the most efficient way.
1688 ;;
1689 ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
1690 ;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
1691 ;; both here so that when this is fixed, they can both be fixed together.
1692 ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
1693 ;; changed too).
1694
1695 (define_insn "move_label_di"
1696   [(set (match_operand:DI 0 "register_operand" "=r")
1697         ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
1698         ; loses the volatil and other flags of the original label_ref.
1699         (match_operand:DI 1 "label_ref_operand" ""))
1700    (set (reg:DI 15) (pc))]
1701   "TARGET_ARCH64"
1702   "*
1703 {
1704   if (get_attr_length (insn) == 2)
1705     return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
1706   else
1707     return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
1708 }"
1709   [(set_attr "type" "multi")
1710    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1711    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1712                                            (const_int 960))
1713                                       (const_int 2)
1714                                       (const_int 5)))])
1715
1716 (define_insn "*sethi_hi"
1717   [(set (match_operand:HI 0 "register_operand" "=r")
1718         (high:HI (match_operand 1 "" "")))]
1719   "check_pic (1)"
1720   "sethi %%hi(%a1),%0"
1721   [(set_attr "type" "move")
1722    (set_attr "length" "1")])
1723
1724 ;; This must appear after the PIC sethi so that the PIC unspec will not
1725 ;; be matched as part of the operand.
1726 (define_insn "*sethi_si"
1727   [(set (match_operand:SI 0 "register_operand" "=r")
1728         (high:SI (match_operand 1 "" "")))]
1729   "check_pic (1)"
1730   "sethi %%hi(%a1),%0"
1731   [(set_attr "type" "move")
1732    (set_attr "length" "1")])
1733
1734 (define_insn "*lo_sum_di_sp32"
1735   [(set (match_operand:DI 0 "register_operand" "=r")
1736         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1737                    (match_operand:DI 2 "immediate_operand" "in")))]
1738   "! TARGET_ARCH64"
1739   "*
1740 {
1741   /* Don't output a 64 bit constant, since we can't trust the assembler to
1742      handle it correctly.  */
1743   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1744     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1745   else if (GET_CODE (operands[2]) == CONST_INT
1746            && HOST_BITS_PER_WIDE_INT > 32
1747            && INTVAL (operands[2]) > 0xffffffff)
1748     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1749
1750   return \"or %L1,%%lo(%a2),%L0\";
1751 }"
1752   ;; Need to set length for this arith insn because operand2
1753   ;; is not an "arith_operand".
1754   [(set_attr "length" "1")])
1755
1756 ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
1757
1758 (define_insn "*lo_sum_di_sp64"
1759   [(set (match_operand:DI 0 "register_operand" "=r")
1760         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1761                    (match_operand:DI 2 "immediate_operand" "in")))]
1762   "TARGET_ARCH64"
1763   "*
1764 {
1765   /* Don't output a 64 bit constant, since we can't trust the assembler to
1766      handle it correctly.  */
1767   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1768     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1769   else if (GET_CODE (operands[2]) == CONST_INT
1770            && HOST_BITS_PER_WIDE_INT > 32
1771            && INTVAL (operands[2]) > 0xffffffff)
1772     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1773
1774   /* Note that we use add here.  This is important because Medium/Anywhere
1775      code model support depends on it.  */
1776   return \"add %1,%%lo(%a2),%0\";
1777 }"
1778   ;; Need to set length for this arith insn because operand2
1779   ;; is not an "arith_operand".
1780   [(set_attr "length" "1")])
1781
1782 (define_insn "*sethi_di_sp32"
1783   [(set (match_operand:DI 0 "register_operand" "=r")
1784         (high:DI (match_operand 1 "" "")))]
1785   "! TARGET_ARCH64 && check_pic (1)"
1786   "*
1787 {
1788   rtx op0 = operands[0];
1789   rtx op1 = operands[1];
1790
1791   if (GET_CODE (op1) == CONST_INT)
1792     {
1793       operands[0] = operand_subword (op0, 1, 0, DImode);
1794       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1795
1796       operands[0] = operand_subword (op0, 0, 0, DImode);
1797       if (INTVAL (op1) < 0)
1798         return \"mov -1,%0\";
1799       else
1800         return \"mov 0,%0\";
1801     }
1802   else if (GET_CODE (op1) == CONST_DOUBLE)
1803     {
1804       operands[0] = operand_subword (op0, 1, 0, DImode);
1805       operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
1806       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1807
1808       operands[0] = operand_subword (op0, 0, 0, DImode);
1809       operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
1810       return singlemove_string (operands);
1811     }
1812   else
1813     abort ();
1814   return \"\";
1815 }"
1816   [(set_attr "type" "move")
1817    (set_attr "length" "2")])
1818
1819 ;;; ??? This pattern originally clobbered a scratch register.  However, this
1820 ;;; is invalid, the movdi pattern may not use a temp register because it
1821 ;;; may be called from reload to reload a DImode value.  In that case, we
1822 ;;; end up with a scratch register that never gets allocated.  To avoid this,
1823 ;;; we use global register 1 which is never otherwise used by gcc as a temp.
1824 ;;; The correct solution here might be to force DImode constants to memory,
1825 ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
1826 ;;; 1 will then no longer need to be considered a fixed reg.
1827
1828 (define_expand "sethi_di_sp64"
1829   [(parallel
1830      [(set (match_operand:DI 0 "register_operand" "")
1831            (high:DI (match_operand 1 "general_operand" "")))
1832       (clobber (reg:DI 1))])]
1833   "TARGET_ARCH64"
1834   "")
1835
1836 (define_insn "*sethi_di_sp64_const"
1837   [(set (match_operand:DI 0 "register_operand" "=r")
1838         (high:DI (match_operand 1 "const_double_operand" "")))
1839    (clobber (reg:DI 1))]
1840   "TARGET_ARCH64 && check_pic (1)"
1841   "*
1842 {
1843 #if HOST_BITS_PER_WIDE_INT == 32
1844   rtx high, low;
1845   
1846   split_double (operands[1], &high, &low);
1847
1848   if (high == const0_rtx)
1849     {
1850       operands[1] = low;
1851       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1852     }
1853   else
1854     {
1855       operands[1] = high;
1856       output_asm_insn (singlemove_string (operands), operands);
1857
1858       operands[1] = low;
1859       output_asm_insn (\"sllx %0,32,%0\", operands);
1860       if (low != const0_rtx)
1861         output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1862     }
1863 #else
1864   rtx op = operands[1];
1865
1866   if (! SPARC_SETHI_P (INTVAL(op)))
1867     {
1868       operands[1] = GEN_INT (INTVAL (op) >> 32);
1869       output_asm_insn (singlemove_string (operands), operands);
1870
1871       output_asm_insn (\"sllx %0,32,%0\", operands);
1872       if (INTVAL (op) & 0xffffffff)
1873         {
1874           operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
1875           output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1876         }
1877     }
1878   else
1879     {
1880       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1881     }
1882 #endif
1883
1884   return \"\";
1885 }"
1886   [(set_attr "type" "move")
1887    (set_attr "length" "5")])
1888
1889 ;; Most of the required support for the various code models is here.
1890 ;; We can do this because sparcs need the high insn to load the address.  We
1891 ;; just need to get high to do the right thing for each code model.  Then each
1892 ;; uses the same "%X+%lo(...)" in the load/store insn, though in the case of
1893 ;; the medium/middle code model "%lo" is written "%l44".
1894
1895 ;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are
1896 ;; always 0.
1897 ;; When TARGET_CM_MEDMID, the executable must be in the low 16 TB of memory.
1898 ;; This corresponds to the low 44 bits, and the %[hml]44 relocs are used.
1899 ;; ??? Not implemented yet.
1900 ;; When TARGET_CM_EMBMEDANY, the text and data segments have a maximum size of
1901 ;; 31 bits and may be located anywhere.  EMBMEDANY_BASE_REG contains the start
1902 ;; address of the data segment, currently %g4.
1903 ;; When TARGET_CM_MEDANY, the text and data segments have a maximum size of 31
1904 ;; bits and may be located anywhere.  The maximum offset from any instruction
1905 ;; to the label _GLOBAL_OFFSET_TABLE_ is 31 bits.
1906
1907 (define_insn "*sethi_di_medlow"
1908   [(set (match_operand:DI 0 "register_operand" "=r")
1909         (high:DI (match_operand 1 "" "")))
1910   ;; The clobber is here because emit_move_sequence assumes the worst case.
1911    (clobber (reg:DI 1))]
1912   "TARGET_CM_MEDLOW && check_pic (1)"
1913   "sethi %%hi(%a1),%0"
1914   [(set_attr "type" "move")
1915    (set_attr "length" "1")])
1916
1917 (define_insn "*sethi_di_medium_pic"
1918   [(set (match_operand:DI 0 "register_operand" "=r")
1919         (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
1920   "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
1921   "sethi %%hi(%a1),%0"
1922   [(set_attr "type" "move")
1923    (set_attr "length" "1")])
1924
1925 ;; WARNING: %0 gets %hi(%1)+%g4.
1926 ;;          You cannot OR in %lo(%1), it must be added in.
1927
1928 (define_insn "*sethi_di_embmedany_data"
1929   [(set (match_operand:DI 0 "register_operand" "=r")
1930         (high:DI (match_operand 1 "data_segment_operand" "")))
1931   ;; The clobber is here because emit_move_sequence assumes the worst case.
1932    (clobber (reg:DI 1))]
1933   "TARGET_CM_EMBMEDANY && check_pic (1)"
1934   "sethi %%hi(%a1),%0; add %0,%_,%0"
1935   [(set_attr "type" "move")
1936    (set_attr "length" "2")])
1937
1938 (define_insn "*sethi_di_embmedany_text"
1939   [(set (match_operand:DI 0 "register_operand" "=r")
1940         (high:DI (match_operand 1 "text_segment_operand" "")))
1941   ;; The clobber is here because emit_move_sequence assumes the worst case.
1942    (clobber (reg:DI 1))]
1943   "TARGET_CM_EMBMEDANY && check_pic (1)"
1944   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1945   [(set_attr "type" "move")
1946    (set_attr "length" "5")])
1947 \f
1948 ;; Move instructions
1949
1950 (define_expand "movqi"
1951   [(set (match_operand:QI 0 "general_operand" "")
1952         (match_operand:QI 1 "general_operand" ""))]
1953   ""
1954   "
1955 {
1956   if (emit_move_sequence (operands, QImode))
1957     DONE;
1958 }")
1959
1960 (define_insn "*movqi_insn"
1961   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1962         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1963   "! TARGET_LIVE_G0
1964    && (register_operand (operands[0], QImode)
1965        || register_operand (operands[1], QImode)
1966        || operands[1] == const0_rtx)"
1967   "@
1968    mov %1,%0
1969    sethi %%hi(%a1),%0
1970    ldub %1,%0
1971    stb %r1,%0"
1972   [(set_attr "type" "move,move,load,store")
1973    (set_attr "length" "1")])
1974
1975 (define_insn "*movqi_insn_liveg0"
1976   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1977         (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
1978   "TARGET_LIVE_G0
1979    && (register_operand (operands[0], QImode)
1980        || register_operand (operands[1], QImode))"
1981   "@
1982    mov %1,%0
1983    and %0,0,%0
1984    and %0,0,%0\;or %0,%1,%0
1985    sethi %%hi(%a1),%0
1986    ldub %1,%0
1987    stb %1,%0"
1988   [(set_attr "type" "move,move,move,move,load,store")
1989    (set_attr "length" "1,1,2,1,1,1")])
1990
1991 (define_insn "*lo_sum_qi"
1992   [(set (match_operand:QI 0 "register_operand" "=r")
1993         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1994                               (match_operand 2 "immediate_operand" "in")) 0))]
1995   ""
1996   "or %1,%%lo(%a2),%0"
1997   [(set_attr "length" "1")])
1998
1999 (define_insn "*store_qi"
2000   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
2001         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
2002    (clobber (match_scratch:SI 2 "=&r"))]
2003   "(reload_completed || reload_in_progress)
2004    && ! TARGET_PTR64"
2005   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
2006   [(set_attr "type" "store")
2007    (set_attr "length" "2")])
2008
2009 (define_expand "movhi"
2010   [(set (match_operand:HI 0 "general_operand" "")
2011         (match_operand:HI 1 "general_operand" ""))]
2012   ""
2013   "
2014 {
2015   if (emit_move_sequence (operands, HImode))
2016     DONE;
2017 }")
2018
2019 (define_insn "*movhi_insn"
2020   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
2021         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
2022   "! TARGET_LIVE_G0
2023    && (register_operand (operands[0], HImode)
2024        || register_operand (operands[1], HImode)
2025        || operands[1] == const0_rtx)"
2026   "@
2027    mov %1,%0
2028    sethi %%hi(%a1),%0
2029    lduh %1,%0
2030    sth %r1,%0"
2031   [(set_attr "type" "move,move,load,store")
2032    (set_attr "length" "1")])
2033
2034 (define_insn "*movhi_insn_liveg0"
2035   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
2036         (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
2037   "TARGET_LIVE_G0
2038    && (register_operand (operands[0], HImode)
2039        || register_operand (operands[1], HImode))"
2040   "@
2041    mov %1,%0
2042    and %0,0,%0
2043    and %0,0,%0\;or %0,%1,%0
2044    sethi %%hi(%a1),%0
2045    lduh %1,%0
2046    sth %1,%0"
2047   [(set_attr "type" "move,move,move,move,load,store")
2048    (set_attr "length" "1,1,2,1,1,1")])
2049
2050 (define_insn "*lo_sum_hi"
2051   [(set (match_operand:HI 0 "register_operand" "=r")
2052         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
2053                    (match_operand 2 "immediate_operand" "in")))]
2054   ""
2055   "or %1,%%lo(%a2),%0"
2056   [(set_attr "length" "1")])
2057
2058 (define_insn "*store_hi"
2059   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
2060         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
2061    (clobber (match_scratch:SI 2 "=&r"))]
2062   "(reload_completed || reload_in_progress)
2063    && ! TARGET_PTR64"
2064   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
2065   [(set_attr "type" "store")
2066    (set_attr "length" "2")])
2067
2068 (define_expand "movsi"
2069   [(set (match_operand:SI 0 "general_operand" "")
2070         (match_operand:SI 1 "general_operand" ""))]
2071   ""
2072   "
2073 {
2074   if (emit_move_sequence (operands, SImode))
2075     DONE;
2076 }")
2077
2078 ;; We must support both 'r' and 'f' registers here, because combine may
2079 ;; convert SFmode hard registers to SImode hard registers when simplifying
2080 ;; subreg sets.
2081
2082 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
2083 ;; problems with register allocation.  Reload might try to put an integer
2084 ;; in an fp register, or an fp number is an integer register.
2085
2086 (define_insn "*movsi_insn"
2087   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q,d")
2088         (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f,J"))]
2089   "! TARGET_LIVE_G0
2090    && (register_operand (operands[0], SImode)
2091        || register_operand (operands[1], SImode)
2092        || operands[1] == const0_rtx)"
2093   "@
2094    mov %1,%0
2095    fmovs %1,%0
2096    sethi %%hi(%a1),%0
2097    ld %1,%0
2098    ld %1,%0
2099    st %r1,%0
2100    st %1,%0
2101    fzeros %0"
2102   [(set_attr "type" "move,fp,move,load,fpload,store,fpstore,fpmove")
2103    (set_attr "length" "1")])
2104
2105 (define_insn "*movsi_insn_liveg0"
2106   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
2107         (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
2108   "TARGET_LIVE_G0
2109    && (register_operand (operands[0], SImode)
2110        || register_operand (operands[1], SImode))"
2111   "@
2112    mov %1,%0
2113    and %0,0,%0
2114    and %0,0,%0\;or %0,%1,%0
2115    fmovs %1,%0
2116    sethi %%hi(%a1),%0
2117    ld %1,%0
2118    ld %1,%0
2119    st %1,%0
2120    st %1,%0"
2121   [(set_attr "type" "move,move,move,fpmove,move,load,fpload,store,fpstore")
2122    (set_attr "length" "1,1,2,1,1,1,1,1,1")])
2123
2124 (define_insn "*store_si"
2125   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
2126         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2127    (clobber (match_scratch:SI 2 "=&r"))]
2128   "(reload_completed || reload_in_progress)
2129    && ! TARGET_PTR64"
2130   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2131   [(set_attr "type" "store")
2132    (set_attr "length" "2")])
2133
2134 (define_expand "movdi"
2135   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
2136         (match_operand:DI 1 "general_operand" ""))]
2137   ""
2138   "
2139 {
2140   if (emit_move_sequence (operands, DImode))
2141     DONE;
2142 }")
2143
2144 ;; V8+ movdi is like regular 32 bit except that a 64 bit zero can be stored
2145 ;; to aligned memory with a single instruction and the ldd/std instructions
2146 ;; are not used.
2147 (define_insn "*movdi_v8plus"
2148   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,Q,r,r,f,f,Q,b")
2149       (match_operand:DI 1 "general_operand" "r,J,r,Q,i,?f,?Q,?f,?J"))]
2150   "TARGET_V8PLUS
2151    && (register_operand (operands[0], DImode)
2152        || register_operand (operands[1], DImode)
2153        || operands[1] == const0_rtx)"
2154   "*
2155 {
2156   if (which_alternative == 1)
2157     return \"stx %%g0,%0\";
2158   if (which_alternative == 8)
2159     return \"fzero %0\";
2160   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2161     return output_fp_move_double (operands);
2162   return output_move_double (operands);
2163 }"
2164   [(set_attr "type" "move,store,store,load,multi,fp,fpload,fpstore,fpmove")
2165    (set_attr "length" "2,1,3,3,3,2,3,3,1")])
2166
2167 ;; ??? The Haifa scheduler does not split instructions after reload if
2168 ;; it also ran before reload.
2169
2170 (define_split
2171   [(set (match_operand:DI 0 "memory_operand" "=m")
2172       (match_operand:DI 1 "register_operand" "r"))]
2173   "TARGET_V8PLUS && !TARGET_ARCH64 && reload_completed
2174    && REGNO (operands[1]) < 32 && ! MEM_VOLATILE_P (operands[0])
2175    && offsettable_memref_p (operands[0])"
2176   [(set (match_dup 2) (match_dup 3))
2177    (set (match_dup 4) (match_dup 5))]
2178   "operands[3] = gen_highpart (SImode, operands[1]);
2179    operands[5] = gen_lowpart (SImode, operands[1]);
2180    operands[4] = adj_offsettable_operand (operands[0], 4);
2181    PUT_MODE (operands[4], SImode);
2182    operands[2] = copy_rtx (operands[0]);
2183    PUT_MODE (operands[2], SImode);")
2184
2185 (define_insn "*movdi_sp32_insn"
2186   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
2187         (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
2188   "! TARGET_ARCH64
2189    && (register_operand (operands[0], DImode)
2190        || register_operand (operands[1], DImode)
2191        || operands[1] == const0_rtx)"
2192   "*
2193 {
2194   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2195     return output_fp_move_double (operands);
2196   return output_move_double (operands);
2197 }"
2198   [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
2199    (set_attr "length" "2,1,1,3,3,3,2,3,3")])
2200
2201 ;;; ??? The trick used below can be extended to load any negative 32 bit
2202 ;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM
2203 ;;; for anything not matching the HIK constraints, which results in 5
2204 ;;; instructions.  Positive 32 bit constants can be loaded in the obvious way
2205 ;;; with sethi/ori.  To extend the trick, in the xor instruction, use 
2206 ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
2207 ;;; This needs the original value of operands[1], not the inverted value.
2208
2209 (define_insn "*movdi_sp64_insn"
2210   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
2211         (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
2212   "TARGET_ARCH64
2213    && (register_operand (operands[0], DImode)
2214        || register_operand (operands[1], DImode)
2215        || operands[1] == const0_rtx)"
2216   "*
2217 {
2218   switch (which_alternative)
2219     {
2220     case 0:
2221       return \"mov %1,%0\";
2222     case 1:
2223       /* Sethi does not sign extend, so we must use a little trickery
2224          to use it for negative numbers.  Invert the constant before
2225          loading it in, then use a xor immediate to invert the loaded bits
2226          (along with the upper 32 bits) to the desired constant.  This
2227          works because the sethi and immediate fields overlap.  */
2228
2229       if ((INTVAL (operands[1]) & 0x80000000) == 0)
2230         return \"sethi %%hi(%a1),%0\";
2231       else
2232         {
2233           operands[1] = GEN_INT (~INTVAL (operands[1]));
2234           output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
2235           /* The low 10 bits are already zero, but invert the rest.
2236              Assemblers don't accept 0x1c00, so use -0x400 instead.  */
2237           return \"xor %0,-0x400,%0\";
2238         }
2239     case 2:
2240       return \"ldx %1,%0\";
2241     case 3:
2242       return \"stx %r1,%0\";
2243     case 4:
2244       return \"mov %1,%0\";
2245     case 5:
2246       return \"ldd %1,%0\";
2247     case 6:
2248       return \"std %1,%0\";
2249     default:
2250       abort ();
2251     }
2252 }"
2253   [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
2254    (set_attr "length" "1,2,1,1,1,1,1")])
2255
2256 ;; ??? There's no symbolic (set (mem:DI ...) ...).
2257 ;; Experimentation with v9 suggested one isn't needed.
2258 \f
2259 ;; Block move insns.
2260
2261 ;; ??? We get better code without it.  See output_block_move in sparc.c.
2262
2263 ;; The definition of this insn does not really explain what it does,
2264 ;; but it should suffice
2265 ;; that anything generated as this insn will be recognized as one
2266 ;; and that it will not successfully combine with anything.
2267 ;(define_expand "movstrsi"
2268 ;  [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
2269 ;                  (mem:BLK (match_operand:BLK 1 "general_operand" "")))
2270 ;             (use (match_operand:SI 2 "nonmemory_operand" ""))
2271 ;             (use (match_operand:SI 3 "immediate_operand" ""))
2272 ;             (clobber (match_dup 0))
2273 ;             (clobber (match_dup 1))
2274 ;             (clobber (match_scratch:SI 4 ""))
2275 ;             (clobber (reg:SI 100))
2276 ;             (clobber (reg:SI 1))])]
2277 ;  ""
2278 ;  "
2279 ;{
2280 ;  /* If the size isn't known, don't emit inline code.  output_block_move
2281 ;     would output code that's much slower than the library function.
2282 ;     Also don't output code for large blocks.  */
2283 ;  if (GET_CODE (operands[2]) != CONST_INT
2284 ;      || GET_CODE (operands[3]) != CONST_INT
2285 ;      || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
2286 ;    FAIL;
2287 ;
2288 ;  operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
2289 ;  operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2290 ;  operands[2] = force_not_mem (operands[2]);
2291 ;}")
2292
2293 ;(define_insn "*block_move_insn"
2294 ;  [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
2295 ;       (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
2296 ;   (use (match_operand:SI 2 "nonmemory_operand" "rn"))
2297 ;   (use (match_operand:SI 3 "immediate_operand" "i"))
2298 ;   (clobber (match_dup 0))
2299 ;   (clobber (match_dup 1))
2300 ;   (clobber (match_scratch:SI 4 "=&r"))
2301 ;   (clobber (reg:SI 100))
2302 ;   (clobber (reg:SI 1))]
2303 ;  ""
2304 ;  "* return output_block_move (operands);"
2305 ;  [(set_attr "type" "multi")
2306 ;   (set_attr "length" "6")])
2307 \f
2308 ;; Floating point move insns
2309
2310 ;; This pattern forces (set (reg:SF ...) (const_double ...))
2311 ;; to be reloaded by putting the constant into memory.
2312 ;; It must come before the more general movsf pattern.
2313 (define_insn "*movsf_const_insn"
2314   [(set (match_operand:SF 0 "general_operand" "=?r,f,m,d")
2315         (match_operand:SF 1 "" "?F,m,G,G"))]
2316   "TARGET_FPU
2317    && GET_CODE (operands[1]) == CONST_DOUBLE
2318    && (GET_CODE (operands[0]) == REG
2319        || fp_zero_operand (operands[1]))"
2320   "*
2321 {
2322   switch (which_alternative)
2323     {
2324     case 0:
2325       return singlemove_string (operands);
2326     case 1:
2327       return \"ld %1,%0\";
2328     case 2:
2329       return \"st %%g0,%0\";
2330     case 3:
2331       return \"fzeros %0\";
2332     default:
2333       abort ();
2334     }
2335 }"
2336   [(set_attr "type" "load,fpload,store,fpmove")
2337    (set_attr "length" "2,1,1,1")])
2338
2339 (define_expand "movsf"
2340   [(set (match_operand:SF 0 "general_operand" "")
2341         (match_operand:SF 1 "general_operand" ""))]
2342   ""
2343   "
2344 {
2345   if (emit_move_sequence (operands, SFmode))
2346     DONE;
2347 }")
2348
2349 (define_insn "*movsf_insn"
2350   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
2351         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
2352   "TARGET_FPU
2353    && (register_operand (operands[0], SFmode)
2354        || register_operand (operands[1], SFmode))"
2355   "@
2356    fmovs %1,%0
2357    mov %1,%0
2358    ld %1,%0
2359    ld %1,%0
2360    st %1,%0
2361    st %1,%0"
2362   [(set_attr "type" "fpmove,move,fpload,load,fpstore,store")])
2363
2364 ;; Exactly the same as above, except that all `f' cases are deleted.
2365 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2366 ;; when -mno-fpu.
2367
2368 (define_insn "*movsf_no_f_insn"
2369   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
2370         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
2371   "! TARGET_FPU
2372    && (register_operand (operands[0], SFmode)
2373        || register_operand (operands[1], SFmode))"
2374   "@
2375    mov %1,%0
2376    ld %1,%0
2377    st %1,%0"
2378   [(set_attr "type" "move,load,store")])
2379
2380 (define_insn "*store_sf"
2381   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
2382         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
2383    (clobber (match_scratch:SI 2 "=&r"))]
2384   "(reload_completed || reload_in_progress)
2385    && ! TARGET_PTR64"
2386   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2387   [(set_attr "type" "store")
2388    (set_attr "length" "2")])
2389
2390 ;; This pattern forces (set (reg:DF ...) (const_double ...))
2391 ;; to be reloaded by putting the constant into memory.
2392 ;; It must come before the more general movdf pattern.
2393
2394 (define_insn "*movdf_const_insn"
2395   [(set (match_operand:DF 0 "general_operand" "=?r,e,o,d")
2396         (match_operand:DF 1 "" "?F,m,G,G"))]
2397   "TARGET_FPU
2398    && GET_CODE (operands[1]) == CONST_DOUBLE
2399    && (GET_CODE (operands[0]) == REG
2400        || fp_zero_operand (operands[1]))"
2401   "*
2402 {
2403   switch (which_alternative)
2404     {
2405     case 0:
2406       return output_move_double (operands);
2407     case 1:
2408       return output_fp_move_double (operands);
2409     case 2:
2410       if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
2411         {
2412           return \"stx %%g0,%0\";
2413         }
2414       else
2415         {
2416           operands[1] = adj_offsettable_operand (operands[0], 4);
2417           return \"st %%g0,%0\;st %%g0,%1\";
2418         }
2419     case 3:
2420       return \"fzero %0\";
2421     default:
2422       abort ();
2423     }
2424 }"
2425   [(set_attr "type" "load,fpload,store,fpmove")
2426    (set_attr "length" "3,3,3,1")])
2427
2428 (define_expand "movdf"
2429   [(set (match_operand:DF 0 "general_operand" "")
2430         (match_operand:DF 1 "general_operand" ""))]
2431   ""
2432   "
2433 {
2434   if (emit_move_sequence (operands, DFmode))
2435     DONE;
2436 }")
2437
2438 (define_insn "*movdf_insn"
2439   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r")
2440         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))]
2441   "TARGET_FPU
2442    && (register_operand (operands[0], DFmode)
2443        || register_operand (operands[1], DFmode))"
2444   "*
2445 {
2446   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2447     return output_fp_move_double (operands);
2448   return output_move_double (operands);
2449 }"
2450   [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
2451    (set_attr "length" "1,1,2,2,3,3,3,3")])
2452
2453 ;; Exactly the same as above, except that all `e' cases are deleted.
2454 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2455 ;; when -mno-fpu.
2456
2457 (define_insn "*movdf_no_e_insn"
2458   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
2459         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
2460   "! TARGET_FPU
2461    && (register_operand (operands[0], DFmode)
2462        || register_operand (operands[1], DFmode))"
2463   "* return output_move_double (operands);"
2464   [(set_attr "type" "store,load,move,store,load")
2465    (set_attr "length" "1,1,2,3,3")])
2466
2467 ;; Must handle overlapping registers here, since parameters can be unaligned
2468 ;; in registers.
2469
2470 (define_split
2471   [(set (match_operand:DF 0 "register_operand" "")
2472         (match_operand:DF 1 "register_operand" ""))]
2473   "! TARGET_ARCH64 && reload_completed
2474    && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
2475    && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
2476   [(set (match_dup 2) (match_dup 3))
2477    (set (match_dup 4) (match_dup 5))]
2478   "
2479 {
2480   rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
2481   rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
2482
2483   if (REGNO (first_set) == REGNO (second_use))
2484     {
2485       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
2486       operands[3] = second_use;
2487       operands[4] = first_set;
2488       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
2489     }
2490   else
2491     {
2492       operands[2] = first_set;
2493       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
2494       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
2495       operands[5] = second_use;
2496     }
2497 }")
2498
2499 (define_insn "*store_df"
2500   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
2501         (match_operand:DF 1 "reg_or_0_operand" "re,G"))
2502    (clobber (match_scratch:SI 2 "=&r,&r"))]
2503   "(reload_completed || reload_in_progress)
2504    && ! TARGET_PTR64"
2505   "*
2506 {
2507   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2508   if (which_alternative == 0)
2509     return \"std %1,[%2+%%lo(%a0)]\";
2510   else
2511     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
2512 }"
2513   [(set_attr "type" "store")
2514    (set_attr "length" "3")])
2515
2516 ;; This pattern forces (set (reg:TF ...) (const_double ...))
2517 ;; to be reloaded by putting the constant into memory.
2518 ;; It must come before the more general movtf pattern.
2519 (define_insn "*movtf_const_insn"
2520   [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
2521         (match_operand:TF 1 "" "?F,m,G"))]
2522   "TARGET_FPU
2523    && GET_CODE (operands[1]) == CONST_DOUBLE
2524    && (GET_CODE (operands[0]) == REG
2525        || fp_zero_operand (operands[1]))"
2526   "*
2527 {
2528   switch (which_alternative)
2529     {
2530     case 0:
2531       return output_move_quad (operands);
2532     case 1:
2533       return output_fp_move_quad (operands);
2534     case 2:
2535       if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
2536         {
2537           operands[1] = adj_offsettable_operand (operands[0], 8);
2538           return \"stx %%g0,%0\;stx %%g0,%1\";
2539         }
2540       else
2541         {
2542           /* ??? Do we run off the end of the array here? */
2543           operands[1] = adj_offsettable_operand (operands[0], 4);
2544           operands[2] = adj_offsettable_operand (operands[0], 8);
2545           operands[3] = adj_offsettable_operand (operands[0], 12);
2546           return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
2547         }
2548     default:
2549       abort ();
2550     }
2551 }"
2552   [(set_attr "type" "load,fpload,store")
2553    (set_attr "length" "5,5,5")])
2554
2555 (define_expand "movtf"
2556   [(set (match_operand:TF 0 "general_operand" "")
2557         (match_operand:TF 1 "general_operand" ""))]
2558   ""
2559   "
2560 {
2561   if (emit_move_sequence (operands, TFmode))
2562     DONE;
2563 }")
2564
2565 (define_insn "*movtf_insn"
2566   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r")
2567         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))]
2568   "TARGET_FPU
2569    && (register_operand (operands[0], TFmode)
2570        || register_operand (operands[1], TFmode))"
2571   "*
2572 {
2573   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2574     return output_fp_move_quad (operands);
2575   return output_move_quad (operands);
2576 }"
2577   [(set_attr "type" "fp,move,fpstore,store,fpload,load")
2578    (set_attr "length" "4,4,5,5,5,5")])
2579
2580 ;; Exactly the same as above, except that all `e' cases are deleted.
2581 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2582 ;; when -mno-fpu.
2583
2584 (define_insn "*movtf_no_e_insn"
2585   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
2586         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
2587   "! TARGET_FPU
2588    && (register_operand (operands[0], TFmode)
2589        || register_operand (operands[1], TFmode))"
2590   "*
2591 {
2592   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2593     return output_fp_move_quad (operands);
2594   return output_move_quad (operands);
2595 }"
2596   [(set_attr "type" "move,store,load")
2597    (set_attr "length" "4,5,5")])
2598
2599 ;; This is disabled because it does not work.  Long doubles have only 8
2600 ;; byte alignment.  Adding an offset of 8 or 12 to an 8 byte aligned %lo may 
2601 ;; cause it to overflow.  See also GO_IF_LEGITIMATE_ADDRESS.
2602 (define_insn "*store_tf"
2603   [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
2604         (match_operand:TF 1 "reg_or_0_operand" "re,G"))
2605    (clobber (match_scratch:SI 2 "=&r,&r"))]
2606   "0 && (reload_completed || reload_in_progress)
2607    && ! TARGET_PTR64"
2608   "*
2609 {
2610   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2611   if (which_alternative == 0)
2612     return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
2613   else
2614     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
2615 }"
2616   [(set_attr "type" "store")
2617    (set_attr "length" "5")])
2618 \f
2619 ;; Sparc V9 conditional move instructions.
2620
2621 ;; We can handle larger constants here for some flavors, but for now we keep
2622 ;; it simple and only allow those constants supported by all flavours.
2623 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
2624 ;; 3 contains the constant if one is present, but we handle either for
2625 ;; generality (sparc.c puts a constant in operand 2).
2626
2627 (define_expand "movqicc"
2628   [(set (match_operand:QI 0 "register_operand" "")
2629         (if_then_else:QI (match_operand 1 "comparison_operator" "")
2630                          (match_operand:QI 2 "arith10_operand" "")
2631                          (match_operand:QI 3 "arith10_operand" "")))]
2632   "TARGET_V9"
2633   "
2634 {
2635   enum rtx_code code = GET_CODE (operands[1]);
2636
2637   if (GET_MODE (sparc_compare_op0) == DImode
2638       && ! TARGET_ARCH64)
2639     FAIL;
2640
2641   if (sparc_compare_op1 == const0_rtx
2642       && GET_CODE (sparc_compare_op0) == REG
2643       && GET_MODE (sparc_compare_op0) == DImode
2644       && v9_regcmp_p (code))
2645     {
2646       operands[1] = gen_rtx (code, DImode,
2647                              sparc_compare_op0, sparc_compare_op1);
2648     }
2649   else
2650     {
2651       rtx cc_reg = gen_compare_reg (code,
2652                                     sparc_compare_op0, sparc_compare_op1);
2653       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2654     }
2655 }")
2656
2657 (define_expand "movhicc"
2658   [(set (match_operand:HI 0 "register_operand" "")
2659         (if_then_else:HI (match_operand 1 "comparison_operator" "")
2660                          (match_operand:HI 2 "arith10_operand" "")
2661                          (match_operand:HI 3 "arith10_operand" "")))]
2662   "TARGET_V9"
2663   "
2664 {
2665   enum rtx_code code = GET_CODE (operands[1]);
2666
2667   if (GET_MODE (sparc_compare_op0) == DImode
2668       && ! TARGET_ARCH64)
2669     FAIL;
2670
2671   if (sparc_compare_op1 == const0_rtx
2672       && GET_CODE (sparc_compare_op0) == REG
2673       && GET_MODE (sparc_compare_op0) == DImode
2674       && v9_regcmp_p (code))
2675     {
2676       operands[1] = gen_rtx (code, DImode,
2677                              sparc_compare_op0, sparc_compare_op1);
2678     }
2679   else
2680     {
2681       rtx cc_reg = gen_compare_reg (code,
2682                                     sparc_compare_op0, sparc_compare_op1);
2683       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2684     }
2685 }")
2686
2687 (define_expand "movsicc"
2688   [(set (match_operand:SI 0 "register_operand" "")
2689         (if_then_else:SI (match_operand 1 "comparison_operator" "")
2690                          (match_operand:SI 2 "arith10_operand" "")
2691                          (match_operand:SI 3 "arith10_operand" "")))]
2692   "TARGET_V9"
2693   "
2694 {
2695   enum rtx_code code = GET_CODE (operands[1]);
2696
2697   if (GET_MODE (sparc_compare_op0) == DImode
2698       && ! TARGET_ARCH64)
2699     FAIL;
2700
2701   if (sparc_compare_op1 == const0_rtx
2702       && GET_CODE (sparc_compare_op0) == REG
2703       && GET_MODE (sparc_compare_op0) == DImode
2704       && v9_regcmp_p (code))
2705     {
2706       operands[1] = gen_rtx (code, DImode,
2707                              sparc_compare_op0, sparc_compare_op1);
2708     }
2709   else
2710     {
2711       rtx cc_reg = gen_compare_reg (code,
2712                                     sparc_compare_op0, sparc_compare_op1);
2713       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2714     }
2715 }")
2716
2717 (define_expand "movdicc"
2718   [(set (match_operand:DI 0 "register_operand" "")
2719         (if_then_else:DI (match_operand 1 "comparison_operator" "")
2720                          (match_operand:DI 2 "arith10_double_operand" "")
2721                          (match_operand:DI 3 "arith10_double_operand" "")))]
2722   "TARGET_ARCH64"
2723   "
2724 {
2725   enum rtx_code code = GET_CODE (operands[1]);
2726
2727   if (sparc_compare_op1 == const0_rtx
2728       && GET_CODE (sparc_compare_op0) == REG
2729       && GET_MODE (sparc_compare_op0) == DImode
2730       && v9_regcmp_p (code))
2731     {
2732       operands[1] = gen_rtx (code, DImode,
2733                              sparc_compare_op0, sparc_compare_op1);
2734     }
2735   else
2736     {
2737       rtx cc_reg = gen_compare_reg (code,
2738                                     sparc_compare_op0, sparc_compare_op1);
2739       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2740     }
2741 }")
2742
2743 (define_expand "movsfcc"
2744   [(set (match_operand:SF 0 "register_operand" "")
2745         (if_then_else:SF (match_operand 1 "comparison_operator" "")
2746                          (match_operand:SF 2 "register_operand" "")
2747                          (match_operand:SF 3 "register_operand" "")))]
2748   "TARGET_V9 && TARGET_FPU"
2749   "
2750 {
2751   enum rtx_code code = GET_CODE (operands[1]);
2752
2753   if (GET_MODE (sparc_compare_op0) == DImode
2754       && ! TARGET_ARCH64)
2755     FAIL;
2756
2757   if (sparc_compare_op1 == const0_rtx
2758       && GET_CODE (sparc_compare_op0) == REG
2759       && GET_MODE (sparc_compare_op0) == DImode
2760       && v9_regcmp_p (code))
2761     {
2762       operands[1] = gen_rtx (code, DImode,
2763                              sparc_compare_op0, sparc_compare_op1);
2764     }
2765   else
2766     {
2767       rtx cc_reg = gen_compare_reg (code,
2768                                     sparc_compare_op0, sparc_compare_op1);
2769       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2770     }
2771 }")
2772
2773 (define_expand "movdfcc"
2774   [(set (match_operand:DF 0 "register_operand" "")
2775         (if_then_else:DF (match_operand 1 "comparison_operator" "")
2776                          (match_operand:DF 2 "register_operand" "")
2777                          (match_operand:DF 3 "register_operand" "")))]
2778   "TARGET_V9 && TARGET_FPU"
2779   "
2780 {
2781   enum rtx_code code = GET_CODE (operands[1]);
2782
2783   if (GET_MODE (sparc_compare_op0) == DImode
2784       && ! TARGET_ARCH64)
2785     FAIL;
2786
2787   if (sparc_compare_op1 == const0_rtx
2788       && GET_CODE (sparc_compare_op0) == REG
2789       && GET_MODE (sparc_compare_op0) == DImode
2790       && v9_regcmp_p (code))
2791     {
2792       operands[1] = gen_rtx (code, DImode,
2793                              sparc_compare_op0, sparc_compare_op1);
2794     }
2795   else
2796     {
2797       rtx cc_reg = gen_compare_reg (code,
2798                                     sparc_compare_op0, sparc_compare_op1);
2799       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2800     }
2801 }")
2802
2803 (define_expand "movtfcc"
2804   [(set (match_operand:TF 0 "register_operand" "")
2805         (if_then_else:TF (match_operand 1 "comparison_operator" "")
2806                          (match_operand:TF 2 "register_operand" "")
2807                          (match_operand:TF 3 "register_operand" "")))]
2808   "TARGET_V9 && TARGET_FPU"
2809   "
2810 {
2811   enum rtx_code code = GET_CODE (operands[1]);
2812
2813   if (GET_MODE (sparc_compare_op0) == DImode
2814       && ! TARGET_ARCH64)
2815     FAIL;
2816
2817   if (sparc_compare_op1 == const0_rtx
2818       && GET_CODE (sparc_compare_op0) == REG
2819       && GET_MODE (sparc_compare_op0) == DImode
2820       && v9_regcmp_p (code))
2821     {
2822       operands[1] = gen_rtx (code, DImode,
2823                              sparc_compare_op0, sparc_compare_op1);
2824     }
2825   else
2826     {
2827       rtx cc_reg = gen_compare_reg (code,
2828                                     sparc_compare_op0, sparc_compare_op1);
2829       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2830     }
2831 }")
2832
2833 ;; Conditional move define_insns.
2834
2835 (define_insn "*movqi_cc_sp64"
2836   [(set (match_operand:QI 0 "register_operand" "=r,r")
2837         (if_then_else:QI (match_operator 1 "comparison_operator"
2838                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2839                                  (const_int 0)])
2840                       (match_operand:QI 3 "arith11_operand" "rL,0")
2841                       (match_operand:QI 4 "arith11_operand" "0,rL")))]
2842   "TARGET_V9"
2843   "@
2844    mov%C1 %x2,%3,%0
2845    mov%c1 %x2,%4,%0"
2846   [(set_attr "type" "cmove")])
2847
2848 (define_insn "*movhi_cc_sp64"
2849   [(set (match_operand:HI 0 "register_operand" "=r,r")
2850         (if_then_else:HI (match_operator 1 "comparison_operator"
2851                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2852                                  (const_int 0)])
2853                       (match_operand:HI 3 "arith11_operand" "rL,0")
2854                       (match_operand:HI 4 "arith11_operand" "0,rL")))]
2855   "TARGET_V9"
2856   "@
2857    mov%C1 %x2,%3,%0
2858    mov%c1 %x2,%4,%0"
2859   [(set_attr "type" "cmove")])
2860
2861 (define_insn "*movsi_cc_sp64"
2862   [(set (match_operand:SI 0 "register_operand" "=r,r")
2863         (if_then_else:SI (match_operator 1 "comparison_operator"
2864                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2865                                  (const_int 0)])
2866                       (match_operand:SI 3 "arith11_operand" "rL,0")
2867                       (match_operand:SI 4 "arith11_operand" "0,rL")))]
2868   "TARGET_V9"
2869   "@
2870    mov%C1 %x2,%3,%0
2871    mov%c1 %x2,%4,%0"
2872   [(set_attr "type" "cmove")])
2873
2874 ;; ??? The constraints of operands 3,4 need work.
2875 (define_insn "*movdi_cc_sp64"
2876   [(set (match_operand:DI 0 "register_operand" "=r,r")
2877         (if_then_else:DI (match_operator 1 "comparison_operator"
2878                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2879                                  (const_int 0)])
2880                       (match_operand:DI 3 "arith11_double_operand" "rLH,0")
2881                       (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
2882   "TARGET_ARCH64"
2883   "@
2884    mov%C1 %x2,%3,%0
2885    mov%c1 %x2,%4,%0"
2886   [(set_attr "type" "cmove")])
2887
2888 (define_insn "*movsf_cc_sp64"
2889   [(set (match_operand:SF 0 "register_operand" "=f,f")
2890         (if_then_else:SF (match_operator 1 "comparison_operator"
2891                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2892                                  (const_int 0)])
2893                       (match_operand:SF 3 "register_operand" "f,0")
2894                       (match_operand:SF 4 "register_operand" "0,f")))]
2895   "TARGET_V9 && TARGET_FPU"
2896   "@
2897    fmovs%C1 %x2,%3,%0
2898    fmovs%c1 %x2,%4,%0"
2899   [(set_attr "type" "fpcmove")])
2900
2901 (define_insn "*movdf_cc_sp64"
2902   [(set (match_operand:DF 0 "register_operand" "=e,e")
2903         (if_then_else:DF (match_operator 1 "comparison_operator"
2904                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2905                                  (const_int 0)])
2906                       (match_operand:DF 3 "register_operand" "e,0")
2907                       (match_operand:DF 4 "register_operand" "0,e")))]
2908   "TARGET_V9 && TARGET_FPU"
2909   "@
2910    fmovd%C1 %x2,%3,%0
2911    fmovd%c1 %x2,%4,%0"
2912   [(set_attr "type" "fpcmove")])
2913
2914 (define_insn "*movtf_cc_sp64"
2915   [(set (match_operand:TF 0 "register_operand" "=e,e")
2916         (if_then_else:TF (match_operator 1 "comparison_operator"
2917                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2918                                  (const_int 0)])
2919                       (match_operand:TF 3 "register_operand" "e,0")
2920                       (match_operand:TF 4 "register_operand" "0,e")))]
2921   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
2922   "@
2923    fmovq%C1 %x2,%3,%0
2924    fmovq%c1 %x2,%4,%0"
2925   [(set_attr "type" "fpcmove")])
2926
2927 (define_insn "*movqi_cc_reg_sp64"
2928   [(set (match_operand:QI 0 "register_operand" "=r,r")
2929         (if_then_else:QI (match_operator 1 "v9_regcmp_op"
2930                                 [(match_operand:DI 2 "register_operand" "r,r")
2931                                  (const_int 0)])
2932                       (match_operand:QI 3 "arith10_operand" "rM,0")
2933                       (match_operand:QI 4 "arith10_operand" "0,rM")))]
2934   "TARGET_ARCH64"
2935   "@
2936    movr%D1 %2,%r3,%0
2937    movr%d1 %2,%r4,%0"
2938   [(set_attr "type" "cmove")])
2939
2940 (define_insn "*movhi_cc_reg_sp64"
2941   [(set (match_operand:HI 0 "register_operand" "=r,r")
2942         (if_then_else:HI (match_operator 1 "v9_regcmp_op"
2943                                 [(match_operand:DI 2 "register_operand" "r,r")
2944                                  (const_int 0)])
2945                       (match_operand:HI 3 "arith10_operand" "rM,0")
2946                       (match_operand:HI 4 "arith10_operand" "0,rM")))]
2947   "TARGET_ARCH64"
2948   "@
2949    movr%D1 %2,%r3,%0
2950    movr%d1 %2,%r4,%0"
2951   [(set_attr "type" "cmove")])
2952
2953 (define_insn "*movsi_cc_reg_sp64"
2954   [(set (match_operand:SI 0 "register_operand" "=r,r")
2955         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
2956                                 [(match_operand:DI 2 "register_operand" "r,r")
2957                                  (const_int 0)])
2958                       (match_operand:SI 3 "arith10_operand" "rM,0")
2959                       (match_operand:SI 4 "arith10_operand" "0,rM")))]
2960   "TARGET_ARCH64"
2961   "@
2962    movr%D1 %2,%r3,%0
2963    movr%d1 %2,%r4,%0"
2964   [(set_attr "type" "cmove")])
2965
2966 ;; ??? The constraints of operands 3,4 need work.
2967 (define_insn "*movdi_cc_reg_sp64"
2968   [(set (match_operand:DI 0 "register_operand" "=r,r")
2969         (if_then_else:DI (match_operator 1 "v9_regcmp_op"
2970                                 [(match_operand:DI 2 "register_operand" "r,r")
2971                                  (const_int 0)])
2972                       (match_operand:DI 3 "arith10_double_operand" "rMH,0")
2973                       (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
2974   "TARGET_ARCH64"
2975   "@
2976    movr%D1 %2,%r3,%0
2977    movr%d1 %2,%r4,%0"
2978   [(set_attr "type" "cmove")])
2979
2980 (define_insn "*movsf_cc_reg_sp64"
2981   [(set (match_operand:SF 0 "register_operand" "=f,f")
2982         (if_then_else:SF (match_operator 1 "v9_regcmp_op"
2983                                 [(match_operand:DI 2 "register_operand" "r,r")
2984                                  (const_int 0)])
2985                       (match_operand:SF 3 "register_operand" "f,0")
2986                       (match_operand:SF 4 "register_operand" "0,f")))]
2987   "TARGET_ARCH64 && TARGET_FPU"
2988   "@
2989    fmovrs%D1 %2,%3,%0
2990    fmovrs%d1 %2,%4,%0"
2991   [(set_attr "type" "fpcmove")])
2992
2993 (define_insn "*movdf_cc_reg_sp64"
2994   [(set (match_operand:DF 0 "register_operand" "=e,e")
2995         (if_then_else:DF (match_operator 1 "v9_regcmp_op"
2996                                 [(match_operand:DI 2 "register_operand" "r,r")
2997                                  (const_int 0)])
2998                       (match_operand:DF 3 "register_operand" "e,0")
2999                       (match_operand:DF 4 "register_operand" "0,e")))]
3000   "TARGET_ARCH64 && TARGET_FPU"
3001   "@
3002    fmovrd%D1 %2,%3,%0
3003    fmovrd%d1 %2,%4,%0"
3004   [(set_attr "type" "fpcmove")])
3005
3006 (define_insn "*movtf_cc_reg_sp64"
3007   [(set (match_operand:TF 0 "register_operand" "=e,e")
3008         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
3009                                 [(match_operand:DI 2 "register_operand" "r,r")
3010                                  (const_int 0)])
3011                       (match_operand:TF 3 "register_operand" "e,0")
3012                       (match_operand:TF 4 "register_operand" "0,e")))]
3013   "TARGET_ARCH64 && TARGET_FPU"
3014   "@
3015    fmovrq%D1 %2,%3,%0
3016    fmovrq%d1 %2,%4,%0"
3017   [(set_attr "type" "fpcmove")])
3018 \f
3019 ;;- zero extension instructions
3020
3021 ;; These patterns originally accepted general_operands, however, slightly
3022 ;; better code is generated by only accepting register_operands, and then
3023 ;; letting combine generate the ldu[hb] insns.
3024
3025 (define_expand "zero_extendhisi2"
3026   [(set (match_operand:SI 0 "register_operand" "")
3027         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
3028   ""
3029   "
3030 {
3031   rtx temp = gen_reg_rtx (SImode);
3032   rtx shift_16 = GEN_INT (16);
3033   int op1_subword = 0;
3034
3035   if (GET_CODE (operand1) == SUBREG)
3036     {
3037       op1_subword = SUBREG_WORD (operand1);
3038       operand1 = XEXP (operand1, 0);
3039     }
3040
3041   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3042                                          op1_subword),
3043                           shift_16));
3044   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
3045   DONE;
3046 }")
3047
3048 (define_insn "*zero_extendhisi2_insn"
3049   [(set (match_operand:SI 0 "register_operand" "=r")
3050         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3051   ""
3052   "lduh %1,%0"
3053   [(set_attr "type" "load")])
3054
3055 (define_expand "zero_extendqihi2"
3056   [(set (match_operand:HI 0 "register_operand" "")
3057         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
3058   ""
3059   "")
3060
3061 (define_insn "*zero_extendqihi2_insn"
3062   [(set (match_operand:HI 0 "register_operand" "=r,r")
3063         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
3064   "GET_CODE (operands[1]) != CONST_INT"
3065   "@
3066    and %1,0xff,%0
3067    ldub %1,%0"
3068   [(set_attr "type" "unary,load")
3069    (set_attr "length" "1")])
3070
3071 (define_expand "zero_extendqisi2"
3072   [(set (match_operand:SI 0 "register_operand" "")
3073         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
3074   ""
3075   "")
3076
3077 (define_insn "*zero_extendqisi2_insn"
3078   [(set (match_operand:SI 0 "register_operand" "=r,r")
3079         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
3080   "GET_CODE (operands[1]) != CONST_INT"
3081   "@
3082    and %1,0xff,%0
3083    ldub %1,%0"
3084   [(set_attr "type" "unary,load")
3085    (set_attr "length" "1")])
3086
3087 (define_expand "zero_extendqidi2"
3088   [(set (match_operand:DI 0 "register_operand" "")
3089         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
3090   "TARGET_ARCH64"
3091   "")
3092
3093 (define_insn "*zero_extendqidi2_insn"
3094   [(set (match_operand:DI 0 "register_operand" "=r,r")
3095         (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
3096   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
3097   "@
3098    and %1,0xff,%0
3099    ldub %1,%0"
3100   [(set_attr "type" "unary,load")
3101    (set_attr "length" "1")])
3102
3103 (define_expand "zero_extendhidi2"
3104   [(set (match_operand:DI 0 "register_operand" "")
3105         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
3106   "TARGET_ARCH64"
3107   "
3108 {
3109   rtx temp = gen_reg_rtx (DImode);
3110   rtx shift_48 = GEN_INT (48);
3111   int op1_subword = 0;
3112
3113   if (GET_CODE (operand1) == SUBREG)
3114     {
3115       op1_subword = SUBREG_WORD (operand1);
3116       operand1 = XEXP (operand1, 0);
3117     }
3118
3119   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3120                                          op1_subword),
3121                           shift_48));
3122   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
3123   DONE;
3124 }")
3125
3126 (define_insn "*zero_extendhidi2_insn"
3127   [(set (match_operand:DI 0 "register_operand" "=r")
3128         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3129   "TARGET_ARCH64"
3130   "lduh %1,%0"
3131   [(set_attr "type" "load")])
3132
3133 ;; ??? Write truncdisi pattern using sra?
3134
3135 (define_expand "zero_extendsidi2"
3136   [(set (match_operand:DI 0 "register_operand" "")
3137         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
3138   "TARGET_ARCH64"
3139   "")
3140
3141 (define_insn "*zero_extendsidi2_insn"
3142   [(set (match_operand:DI 0 "register_operand" "=r,r")
3143         (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
3144   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
3145   "@
3146    srl %1,0,%0
3147    lduw %1,%0"
3148   [(set_attr "type" "unary,load")
3149    (set_attr "length" "1")])
3150
3151 ;; Simplify comparisons of extended values.
3152
3153 (define_insn "*cmp_zero_extendqisi2"
3154   [(set (reg:CC 100)
3155         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
3156                     (const_int 0)))]
3157   ""
3158   "andcc %0,0xff,%%g0"
3159   [(set_attr "type" "compare")])
3160
3161 (define_insn "*cmp_zero_extendqisi2_set"
3162   [(set (reg:CC 100)
3163         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
3164                     (const_int 0)))
3165    (set (match_operand:SI 0 "register_operand" "=r")
3166         (zero_extend:SI (match_dup 1)))]
3167   ""
3168   "andcc %1,0xff,%0"
3169   [(set_attr "type" "unary")])
3170
3171 ;; Similarly, handle SI->QI mode truncation followed by a compare.
3172
3173 (define_insn "*cmp_siqi_trunc"
3174   [(set (reg:CC 100)
3175         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
3176                     (const_int 0)))]
3177   ""
3178   "andcc %0,0xff,%%g0"
3179   [(set_attr "type" "compare")])
3180
3181 (define_insn "*cmp_siqi_trunc_set"
3182   [(set (reg:CC 100)
3183         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
3184                     (const_int 0)))
3185    (set (match_operand:QI 0 "register_operand" "=r")
3186         (match_dup 1))]
3187   ""
3188   "andcc %1,0xff,%0"
3189   [(set_attr "type" "unary")])
3190 \f
3191 ;;- sign extension instructions
3192
3193 ;; These patterns originally accepted general_operands, however, slightly
3194 ;; better code is generated by only accepting register_operands, and then
3195 ;; letting combine generate the lds[hb] insns.
3196
3197 (define_expand "extendhisi2"
3198   [(set (match_operand:SI 0 "register_operand" "")
3199         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
3200   ""
3201   "
3202 {
3203   rtx temp = gen_reg_rtx (SImode);
3204   rtx shift_16 = GEN_INT (16);
3205   int op1_subword = 0;
3206
3207   if (GET_CODE (operand1) == SUBREG)
3208     {
3209       op1_subword = SUBREG_WORD (operand1);
3210       operand1 = XEXP (operand1, 0);
3211     }
3212
3213   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3214                                          op1_subword),
3215                           shift_16));
3216   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
3217   DONE;
3218 }")
3219
3220 (define_insn "*sign_extendhisi2_insn"
3221   [(set (match_operand:SI 0 "register_operand" "=r")
3222         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3223   ""
3224   "ldsh %1,%0"
3225   [(set_attr "type" "sload")])
3226
3227 (define_expand "extendqihi2"
3228   [(set (match_operand:HI 0 "register_operand" "")
3229         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
3230   ""
3231   "
3232 {
3233   rtx temp = gen_reg_rtx (SImode);
3234   rtx shift_24 = GEN_INT (24);
3235   int op1_subword = 0;
3236   int op0_subword = 0;
3237
3238   if (GET_CODE (operand1) == SUBREG)
3239     {
3240       op1_subword = SUBREG_WORD (operand1);
3241       operand1 = XEXP (operand1, 0);
3242     }
3243   if (GET_CODE (operand0) == SUBREG)
3244     {
3245       op0_subword = SUBREG_WORD (operand0);
3246       operand0 = XEXP (operand0, 0);
3247     }
3248   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3249                                          op1_subword),
3250                           shift_24));
3251   if (GET_MODE (operand0) != SImode)
3252     operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword);
3253   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3254   DONE;
3255 }")
3256
3257 (define_insn "*sign_extendqihi2_insn"
3258   [(set (match_operand:HI 0 "register_operand" "=r")
3259         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3260   ""
3261   "ldsb %1,%0"
3262   [(set_attr "type" "sload")])
3263
3264 (define_expand "extendqisi2"
3265   [(set (match_operand:SI 0 "register_operand" "")
3266         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
3267   ""
3268   "
3269 {
3270   rtx temp = gen_reg_rtx (SImode);
3271   rtx shift_24 = GEN_INT (24);
3272   int op1_subword = 0;
3273
3274   if (GET_CODE (operand1) == SUBREG)
3275     {
3276       op1_subword = SUBREG_WORD (operand1);
3277       operand1 = XEXP (operand1, 0);
3278     }
3279
3280   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3281                                          op1_subword),
3282                           shift_24));
3283   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3284   DONE;
3285 }")
3286
3287 (define_insn "*sign_extendqisi2_insn"
3288   [(set (match_operand:SI 0 "register_operand" "=r")
3289         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3290   ""
3291   "ldsb %1,%0"
3292   [(set_attr "type" "sload")])
3293
3294 (define_expand "extendqidi2"
3295   [(set (match_operand:DI 0 "register_operand" "")
3296         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
3297   "TARGET_ARCH64"
3298   "
3299 {
3300   rtx temp = gen_reg_rtx (DImode);
3301   rtx shift_56 = GEN_INT (56);
3302   int op1_subword = 0;
3303
3304   if (GET_CODE (operand1) == SUBREG)
3305     {
3306       op1_subword = SUBREG_WORD (operand1);
3307       operand1 = XEXP (operand1, 0);
3308     }
3309
3310   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3311                                          op1_subword),
3312                           shift_56));
3313   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
3314   DONE;
3315 }")
3316
3317 (define_insn "*sign_extendqidi2_insn"
3318   [(set (match_operand:DI 0 "register_operand" "=r")
3319         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
3320   "TARGET_ARCH64"
3321   "ldsb %1,%0"
3322   [(set_attr "type" "sload")])
3323
3324 (define_expand "extendhidi2"
3325   [(set (match_operand:DI 0 "register_operand" "")
3326         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
3327   "TARGET_ARCH64"
3328   "
3329 {
3330   rtx temp = gen_reg_rtx (DImode);
3331   rtx shift_48 = GEN_INT (48);
3332   int op1_subword = 0;
3333
3334   if (GET_CODE (operand1) == SUBREG)
3335     {
3336       op1_subword = SUBREG_WORD (operand1);
3337       operand1 = XEXP (operand1, 0);
3338     }
3339
3340   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3341                                          op1_subword),
3342                           shift_48));
3343   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
3344   DONE;
3345 }")
3346
3347 (define_insn "*sign_extendhidi2_insn"
3348   [(set (match_operand:DI 0 "register_operand" "=r")
3349         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3350   "TARGET_ARCH64"
3351   "ldsh %1,%0"
3352   [(set_attr "type" "load")])
3353
3354 (define_expand "extendsidi2"
3355   [(set (match_operand:DI 0 "register_operand" "")
3356         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
3357   "TARGET_ARCH64"
3358   "")
3359
3360 (define_insn "*sign_extendsidi2_insn"
3361   [(set (match_operand:DI 0 "register_operand" "=r,r")
3362         (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
3363   "TARGET_ARCH64"
3364   "@
3365   sra %1,0,%0
3366   ldsw %1,%0"
3367   [(set_attr "type" "unary,sload")
3368    (set_attr "length" "1")])
3369 \f
3370 ;; Special pattern for optimizing bit-field compares.  This is needed
3371 ;; because combine uses this as a canonical form.
3372
3373 (define_insn "*cmp_zero_extract"
3374   [(set (reg:CC 100)
3375         (compare:CC
3376          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
3377                           (match_operand:SI 1 "small_int" "n")
3378                           (match_operand:SI 2 "small_int" "n"))
3379          (const_int 0)))]
3380   "INTVAL (operands[2]) > 19"
3381   "*
3382 {
3383   int len = INTVAL (operands[1]);
3384   int pos = 32 - INTVAL (operands[2]) - len;
3385   unsigned mask = ((1 << len) - 1) << pos;
3386
3387   operands[1] = GEN_INT (mask);
3388   return \"andcc %0,%1,%%g0\";
3389 }")
3390
3391 (define_insn "*cmp_zero_extract_sp64"
3392   [(set (reg:CCX 100)
3393         (compare:CCX
3394          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
3395                           (match_operand:SI 1 "small_int" "n")
3396                           (match_operand:SI 2 "small_int" "n"))
3397          (const_int 0)))]
3398   "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
3399   "*
3400 {
3401   int len = INTVAL (operands[1]);
3402   int pos = 64 - INTVAL (operands[2]) - len;
3403   unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
3404
3405   operands[1] = GEN_INT (mask);
3406   return \"andcc %0,%1,%%g0\";
3407 }")
3408 \f
3409 ;; Conversions between float, double and long double.
3410
3411 (define_insn "extendsfdf2"
3412   [(set (match_operand:DF 0 "register_operand" "=e")
3413         (float_extend:DF
3414          (match_operand:SF 1 "register_operand" "f")))]
3415   "TARGET_FPU"
3416   "fstod %1,%0"
3417   [(set_attr "type" "fp")])
3418
3419 (define_insn "extendsftf2"
3420   [(set (match_operand:TF 0 "register_operand" "=e")
3421         (float_extend:TF
3422          (match_operand:SF 1 "register_operand" "f")))]
3423   "TARGET_FPU && TARGET_HARD_QUAD"
3424   "fstoq %1,%0"
3425   [(set_attr "type" "fp")])
3426
3427 (define_insn "extenddftf2"
3428   [(set (match_operand:TF 0 "register_operand" "=e")
3429         (float_extend:TF
3430          (match_operand:DF 1 "register_operand" "e")))]
3431   "TARGET_FPU && TARGET_HARD_QUAD"
3432   "fdtoq %1,%0"
3433   [(set_attr "type" "fp")])
3434
3435 (define_insn "truncdfsf2"
3436   [(set (match_operand:SF 0 "register_operand" "=f")
3437         (float_truncate:SF
3438          (match_operand:DF 1 "register_operand" "e")))]
3439   "TARGET_FPU"
3440   "fdtos %1,%0"
3441   [(set_attr "type" "fp")])
3442
3443 (define_insn "trunctfsf2"
3444   [(set (match_operand:SF 0 "register_operand" "=f")
3445         (float_truncate:SF
3446          (match_operand:TF 1 "register_operand" "e")))]
3447   "TARGET_FPU && TARGET_HARD_QUAD"
3448   "fqtos %1,%0"
3449   [(set_attr "type" "fp")])
3450
3451 (define_insn "trunctfdf2"
3452   [(set (match_operand:DF 0 "register_operand" "=e")
3453         (float_truncate:DF
3454          (match_operand:TF 1 "register_operand" "e")))]
3455   "TARGET_FPU && TARGET_HARD_QUAD"
3456   "fqtod %1,%0"
3457   [(set_attr "type" "fp")])
3458 \f
3459 ;; Conversion between fixed point and floating point.
3460
3461 (define_insn "floatsisf2"
3462   [(set (match_operand:SF 0 "register_operand" "=f")
3463         (float:SF (match_operand:SI 1 "register_operand" "f")))]
3464   "TARGET_FPU"
3465   "fitos %1,%0"
3466   [(set_attr "type" "fp")])
3467
3468 (define_insn "floatsidf2"
3469   [(set (match_operand:DF 0 "register_operand" "=e")
3470         (float:DF (match_operand:SI 1 "register_operand" "f")))]
3471   "TARGET_FPU"
3472   "fitod %1,%0"
3473   [(set_attr "type" "fp")])
3474
3475 (define_insn "floatsitf2"
3476   [(set (match_operand:TF 0 "register_operand" "=e")
3477         (float:TF (match_operand:SI 1 "register_operand" "f")))]
3478   "TARGET_FPU && TARGET_HARD_QUAD"
3479   "fitoq %1,%0"
3480   [(set_attr "type" "fp")])
3481
3482 ;; Now the same for 64 bit sources.
3483 ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2).
3484
3485 (define_expand "floatdisf2"
3486   [(parallel [(set (match_operand:SF 0 "register_operand" "")
3487                    (float:SF (match_operand:DI 1 "general_operand" "")))
3488               (clobber (match_dup 2))
3489               (clobber (match_dup 3))])]
3490   "TARGET_ARCH64 && TARGET_FPU"
3491   "
3492 {
3493   operands[2] = gen_reg_rtx (DFmode);
3494   operands[3] = sparc64_fpconv_stack_temp ();
3495 }")
3496
3497 (define_expand "floatdidf2"
3498   [(parallel [(set (match_operand:DF 0 "register_operand" "")
3499                    (float:DF (match_operand:DI 1 "general_operand" "")))
3500               (clobber (match_dup 2))
3501               (clobber (match_dup 3))])]
3502   "TARGET_ARCH64 && TARGET_FPU"
3503   "
3504 {
3505   operands[2] = gen_reg_rtx (DFmode);
3506   operands[3] = sparc64_fpconv_stack_temp ();
3507 }")
3508
3509 (define_expand "floatditf2"
3510   [(parallel [(set (match_operand:TF 0 "register_operand" "")
3511                    (float:TF (match_operand:DI 1 "general_operand" "")))
3512               (clobber (match_dup 2))
3513               (clobber (match_dup 3))])]
3514   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3515   "
3516 {
3517   operands[2] = gen_reg_rtx (DFmode);
3518   operands[3] = sparc64_fpconv_stack_temp ();
3519 }")
3520
3521 (define_insn "*floatdisf2_insn"
3522   [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
3523                    (float:SF (match_operand:DI 1 "general_operand" "rm")))
3524               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3525               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3526   "TARGET_ARCH64 && TARGET_FPU"
3527   "*
3528 {
3529   if (GET_CODE (operands[1]) == MEM)
3530     output_asm_insn (\"ldd %1,%2\", operands);
3531   else
3532     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3533   return \"fxtos %2,%0\";
3534 }"
3535   [(set_attr "type" "fp")
3536    (set_attr "length" "3")])
3537
3538 (define_insn "*floatdidf2_insn"
3539   [(parallel [(set (match_operand:DF 0 "register_operand" "=e")
3540                    (float:DF (match_operand:DI 1 "general_operand" "rm")))
3541               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3542               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3543   "TARGET_ARCH64 && TARGET_FPU"
3544   "*
3545 {
3546   if (GET_CODE (operands[1]) == MEM)
3547     output_asm_insn (\"ldd %1,%2\", operands);
3548   else
3549     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3550   return \"fxtod %2,%0\";
3551 }"
3552   [(set_attr "type" "fp")
3553    (set_attr "length" "3")])
3554
3555 (define_insn "*floatditf2_insn"
3556   [(parallel [(set (match_operand:TF 0 "register_operand" "=e")
3557                    (float:TF (match_operand:DI 1 "general_operand" "rm")))
3558               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3559               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3560   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3561   "*
3562 {
3563   if (GET_CODE (operands[1]) == MEM)
3564     output_asm_insn (\"ldd %1,%2\", operands);
3565   else
3566     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3567   return \"fxtoq %2,%0\";
3568 }"
3569   [(set_attr "type" "fp")
3570    (set_attr "length" "3")])
3571
3572 ;; ??? Ideally, these are what we would like to use.
3573
3574 (define_insn "floatdisf2_sp64"
3575   [(set (match_operand:SF 0 "register_operand" "=f")
3576         (float:SF (match_operand:DI 1 "register_operand" "e")))]
3577   "0 && TARGET_ARCH64 && TARGET_FPU"
3578   "fxtos %1,%0"
3579   [(set_attr "type" "fp")])
3580
3581 (define_insn "floatdidf2_sp64"
3582   [(set (match_operand:DF 0 "register_operand" "=e")
3583         (float:DF (match_operand:DI 1 "register_operand" "e")))]
3584   "0 && TARGET_ARCH64 && TARGET_FPU"
3585   "fxtod %1,%0"
3586   [(set_attr "type" "fp")])
3587
3588 (define_insn "floatditf2_sp64"
3589   [(set (match_operand:TF 0 "register_operand" "=e")
3590         (float:TF (match_operand:DI 1 "register_operand" "e")))]
3591   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3592   "fxtoq %1,%0"
3593   [(set_attr "type" "fp")])
3594
3595 ;; Convert a float to an actual integer.
3596 ;; Truncation is performed as part of the conversion.
3597
3598 (define_insn "fix_truncsfsi2"
3599   [(set (match_operand:SI 0 "register_operand" "=f")
3600         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3601   "TARGET_FPU"
3602   "fstoi %1,%0"
3603   [(set_attr "type" "fp")])
3604
3605 (define_insn "fix_truncdfsi2"
3606   [(set (match_operand:SI 0 "register_operand" "=f")
3607         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3608   "TARGET_FPU"
3609   "fdtoi %1,%0"
3610   [(set_attr "type" "fp")])
3611
3612 (define_insn "fix_trunctfsi2"
3613   [(set (match_operand:SI 0 "register_operand" "=f")
3614         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3615   "TARGET_FPU && TARGET_HARD_QUAD"
3616   "fqtoi %1,%0"
3617   [(set_attr "type" "fp")])
3618
3619 ;; Now the same, for 64-bit targets
3620 ;; ??? We try to work around an interesting problem.
3621 ;; If gcc tries to do a subreg on the result it will get the wrong answer:
3622 ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as
3623 ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change
3624 ;; the "0" to a "1".  One could enhance alter_subreg but it is not clear how to
3625 ;; do this cleanly.
3626
3627 (define_expand "fix_truncsfdi2"
3628   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3629                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
3630               (clobber (match_dup 2))
3631               (clobber (match_dup 3))])]
3632   "TARGET_ARCH64 && TARGET_FPU"
3633   "
3634 {
3635   operands[2] = gen_reg_rtx (DFmode);
3636   operands[3] = sparc64_fpconv_stack_temp ();
3637 }")
3638
3639 (define_expand "fix_truncdfdi2"
3640   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3641                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
3642               (clobber (match_dup 2))
3643               (clobber (match_dup 3))])]
3644   "TARGET_ARCH64 && TARGET_FPU"
3645   "
3646 {
3647   operands[2] = gen_reg_rtx (DFmode);
3648   operands[3] = sparc64_fpconv_stack_temp ();
3649 }")
3650
3651 (define_expand "fix_trunctfdi2"
3652   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3653                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" ""))))
3654               (clobber (match_dup 2))
3655               (clobber (match_dup 3))])]
3656   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3657   "
3658 {
3659   operands[2] = gen_reg_rtx (DFmode);
3660   operands[3] = sparc64_fpconv_stack_temp ();
3661 }")
3662
3663 (define_insn "*fix_truncsfdi2_insn"
3664   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3665                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
3666               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3667               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3668   "TARGET_ARCH64 && TARGET_FPU"
3669   "*
3670 {
3671   output_asm_insn (\"fstox %1,%2\", operands);
3672   if (GET_CODE (operands[0]) == MEM)
3673     return \"std %2,%0\";
3674   else
3675     return \"std %2,%3\;ldx %3,%0\";
3676 }"
3677   [(set_attr "type" "fp")
3678    (set_attr "length" "3")])
3679
3680 (define_insn "*fix_truncdfdi2_insn"
3681   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3682                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))
3683               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3684               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3685   "TARGET_ARCH64 && TARGET_FPU"
3686   "*
3687 {
3688   output_asm_insn (\"fdtox %1,%2\", operands);
3689   if (GET_CODE (operands[0]) == MEM)
3690     return \"std %2,%0\";
3691   else
3692     return \"std %2,%3\;ldx %3,%0\";
3693 }"
3694   [(set_attr "type" "fp")
3695    (set_attr "length" "3")])
3696
3697 (define_insn "*fix_trunctfdi2_insn"
3698   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3699                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))
3700               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3701               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3702   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3703   "*
3704 {
3705   output_asm_insn (\"fqtox %1,%2\", operands);
3706   if (GET_CODE (operands[0]) == MEM)
3707     return \"std %2,%0\";
3708   else
3709     return \"std %2,%3\;ldx %3,%0\";
3710 }"
3711   [(set_attr "type" "fp")
3712    (set_attr "length" "3")])
3713
3714 ;; ??? Ideally, these are what we would like to use.
3715
3716 (define_insn "fix_truncsfdi2_sp64"
3717   [(set (match_operand:DI 0 "register_operand" "=e")
3718         (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3719   "0 && TARGET_ARCH64 && TARGET_FPU"
3720   "fstox %1,%0"
3721   [(set_attr "type" "fp")])
3722
3723 (define_insn "fix_truncdfdi2_sp64"
3724   [(set (match_operand:DI 0 "register_operand" "=e")
3725         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3726   "0 && TARGET_ARCH64 && TARGET_FPU"
3727   "fdtox %1,%0"
3728   [(set_attr "type" "fp")])
3729
3730 (define_insn "fix_trunctfdi2_sp64"
3731   [(set (match_operand:DI 0 "register_operand" "=e")
3732         (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3733   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3734   "fqtox %1,%0"
3735   [(set_attr "type" "fp")])
3736 \f
3737 ;;- arithmetic instructions
3738
3739 (define_expand "adddi3"
3740   [(set (match_operand:DI 0 "register_operand" "=r")
3741         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3742                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3743   ""
3744   "
3745 {
3746   if (! TARGET_ARCH64)
3747     {
3748       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3749                           gen_rtx (SET, VOIDmode, operands[0],
3750                                    gen_rtx (PLUS, DImode, operands[1],
3751                                                   operands[2])),
3752                           gen_rtx (CLOBBER, VOIDmode,
3753                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3754       DONE;
3755     }
3756 }")
3757
3758 (define_insn "*adddi3_sp32"
3759   [(set (match_operand:DI 0 "register_operand" "=r")
3760         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3761                  (match_operand:DI 2 "arith_double_operand" "rHI")))
3762    (clobber (reg:SI 100))]
3763   "! TARGET_ARCH64"
3764   "*
3765 {
3766   rtx op2 = operands[2];
3767
3768   if (GET_CODE (op2) == CONST_INT
3769       || GET_CODE (op2) == CONST_DOUBLE)
3770     {
3771       rtx xoperands[4];
3772       xoperands[0] = operands[0];
3773       xoperands[1] = operands[1];
3774       if (WORDS_BIG_ENDIAN)
3775         split_double (op2, &xoperands[2], &xoperands[3]);
3776       else
3777         split_double (op2, &xoperands[3], &xoperands[2]);
3778       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3779         output_asm_insn (\"add %H1,%2,%H0\", xoperands);
3780       else
3781         output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
3782       return \"\";
3783     }
3784   return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
3785 }"
3786   [(set_attr "length" "2")])
3787
3788 (define_insn ""
3789   [(set (match_operand:DI 0 "register_operand" "=r")
3790       (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3791                (match_operand:DI 2 "register_operand" "r")))
3792    (clobber (reg:SI 100))]
3793   "! TARGET_ARCH64"
3794   "addcc %L2,%1,%L0\;addx %H2,0,%H0"
3795   [(set_attr "type" "multi")])
3796
3797 (define_insn "*adddi3_sp64"
3798   [(set (match_operand:DI 0 "register_operand" "=r")
3799         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3800                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3801   "TARGET_ARCH64"
3802   "add %1,%2,%0")
3803
3804 (define_insn "addsi3"
3805   [(set (match_operand:SI 0 "register_operand" "=r,d")
3806         (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
3807                  (match_operand:SI 2 "arith_operand" "rI,d")))]
3808   ""
3809   "@
3810    add %1,%2,%0
3811    fpadd32s %1,%2,%0"
3812   [(set_attr "type" "ialu,fp")])
3813
3814 (define_insn "*cmp_cc_plus"
3815   [(set (reg:CC_NOOV 100)
3816         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
3817                                   (match_operand:SI 1 "arith_operand" "rI"))
3818                          (const_int 0)))]
3819   ""
3820   "addcc %0,%1,%%g0"
3821   [(set_attr "type" "compare")])
3822
3823 (define_insn "*cmp_ccx_plus"
3824   [(set (reg:CCX_NOOV 100)
3825         (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
3826                                    (match_operand:DI 1 "arith_double_operand" "rHI"))
3827                           (const_int 0)))]
3828   "TARGET_ARCH64"
3829   "addcc %0,%1,%%g0"
3830   [(set_attr "type" "compare")])
3831
3832 (define_insn "*cmp_cc_plus_set"
3833   [(set (reg:CC_NOOV 100)
3834         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3835                                   (match_operand:SI 2 "arith_operand" "rI"))
3836                          (const_int 0)))
3837    (set (match_operand:SI 0 "register_operand" "=r")
3838         (plus:SI (match_dup 1) (match_dup 2)))]
3839   ""
3840   "addcc %1,%2,%0")
3841
3842 (define_insn "*cmp_ccx_plus_set"
3843   [(set (reg:CCX_NOOV 100)
3844         (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3845                                    (match_operand:DI 2 "arith_double_operand" "rHI"))
3846                           (const_int 0)))
3847    (set (match_operand:DI 0 "register_operand" "=r")
3848         (plus:DI (match_dup 1) (match_dup 2)))]
3849   "TARGET_ARCH64"
3850   "addcc %1,%2,%0")
3851
3852 (define_expand "subdi3"
3853   [(set (match_operand:DI 0 "register_operand" "=r")
3854         (minus:DI (match_operand:DI 1 "register_operand" "r")
3855                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3856   ""
3857   "
3858 {
3859   if (! TARGET_ARCH64)
3860     {
3861       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3862                           gen_rtx (SET, VOIDmode, operands[0],
3863                                    gen_rtx (MINUS, DImode, operands[1],
3864                                                    operands[2])),
3865                           gen_rtx (CLOBBER, VOIDmode,
3866                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3867       DONE;
3868     }
3869 }")
3870
3871 (define_insn "*subdi3_sp32"
3872   [(set (match_operand:DI 0 "register_operand" "=r")
3873         (minus:DI (match_operand:DI 1 "register_operand" "r")
3874                   (match_operand:DI 2 "arith_double_operand" "rHI")))
3875    (clobber (reg:SI 100))]
3876   "! TARGET_ARCH64"
3877   "*
3878 {
3879   rtx op2 = operands[2];
3880
3881   if (GET_CODE (op2) == CONST_INT
3882       || GET_CODE (op2) == CONST_DOUBLE)
3883     {
3884       rtx xoperands[4];
3885       xoperands[0] = operands[0];
3886       xoperands[1] = operands[1];
3887       if (WORDS_BIG_ENDIAN)
3888         split_double (op2, &xoperands[2], &xoperands[3]);
3889       else
3890         split_double (op2, &xoperands[3], &xoperands[2]);
3891       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3892         output_asm_insn (\"sub %H1,%2,%H0\", xoperands);
3893       else
3894         output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
3895       return \"\";
3896     }
3897   return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
3898 }"
3899   [(set_attr "length" "2")])
3900
3901 (define_insn ""
3902   [(set (match_operand:DI 0 "register_operand" "=r")
3903       (minus:DI (match_operand:DI 1 "register_operand" "r")
3904                 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
3905    (clobber (reg:SI 100))]
3906   "! TARGET_ARCH64"
3907   "subcc %L1,%2,%L0\;addx %H1,0,%H0"
3908   [(set_attr "type" "multi")])
3909
3910 (define_insn "*subdi3_sp64"
3911   [(set (match_operand:DI 0 "register_operand" "=r")
3912         (minus:DI (match_operand:DI 1 "register_operand" "r")
3913                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3914   "TARGET_ARCH64"
3915   "sub %1,%2,%0")
3916
3917 (define_insn "subsi3"
3918   [(set (match_operand:SI 0 "register_operand" "=r,d")
3919         (minus:SI (match_operand:SI 1 "register_operand" "r,d")
3920                   (match_operand:SI 2 "arith_operand" "rI,d")))]
3921   ""
3922   "@
3923    sub %1,%2,%0
3924    fpsub32s %1,%2,%0"
3925   [(set_attr "type" "ialu,fp")])
3926
3927 (define_insn "*cmp_minus_cc"
3928   [(set (reg:CC_NOOV 100)
3929         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
3930                                    (match_operand:SI 1 "arith_operand" "rI"))
3931                          (const_int 0)))]
3932   ""
3933   "subcc %0,%1,%%g0"
3934   [(set_attr "type" "compare")])
3935
3936 (define_insn "*cmp_minus_ccx"
3937   [(set (reg:CCX_NOOV 100)
3938         (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
3939                                     (match_operand:DI 1 "arith_double_operand" "rHI"))
3940                           (const_int 0)))]
3941   "TARGET_ARCH64"
3942   "subcc %0,%1,%%g0"
3943   [(set_attr "type" "compare")])
3944
3945 (define_insn "*cmp_minus_cc_set"
3946   [(set (reg:CC_NOOV 100)
3947         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
3948                                    (match_operand:SI 2 "arith_operand" "rI"))
3949                          (const_int 0)))
3950    (set (match_operand:SI 0 "register_operand" "=r")
3951         (minus:SI (match_dup 1) (match_dup 2)))]
3952   ""
3953   "subcc %1,%2,%0")
3954
3955 (define_insn "*cmp_minus_ccx_set"
3956   [(set (reg:CCX_NOOV 100)
3957         (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
3958                                     (match_operand:DI 2 "arith_double_operand" "rHI"))
3959                           (const_int 0)))
3960    (set (match_operand:DI 0 "register_operand" "=r")
3961         (minus:DI (match_dup 1) (match_dup 2)))]
3962   "TARGET_ARCH64"
3963   "subcc %1,%2,%0")
3964 \f
3965 ;; Integer Multiply/Divide.
3966
3967 ;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't
3968 ;; we used.  We still use them in 32 bit v9 compilers.
3969 ;; The 64 bit v9 compiler will (/should) widen the args and use muldi3.
3970
3971 (define_insn "mulsi3"
3972   [(set (match_operand:SI 0 "register_operand" "=r")
3973         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3974                  (match_operand:SI 2 "arith_operand" "rI")))]
3975   "TARGET_HARD_MUL"
3976   "smul %1,%2,%0"
3977   [(set_attr "type" "imul")])
3978
3979 (define_insn "muldi3"
3980   [(set (match_operand:DI 0 "register_operand" "=r")
3981         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
3982                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3983   "TARGET_ARCH64"
3984   "mulx %1,%2,%0")
3985
3986 ;; It is not known whether this will match.
3987
3988 (define_insn "*cmp_mul_set"
3989   [(set (match_operand:SI 0 "register_operand" "=r")
3990         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3991                  (match_operand:SI 2 "arith_operand" "rI")))
3992    (set (reg:CC_NOOV 100)
3993         (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
3994                          (const_int 0)))]
3995   "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
3996   "smulcc %1,%2,%0"
3997   [(set_attr "type" "imul")])
3998
3999 (define_expand "mulsidi3"
4000   [(set (match_operand:DI 0 "register_operand" "")
4001         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
4002                  (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
4003   "TARGET_HARD_MUL"
4004   "
4005 {
4006   if (CONSTANT_P (operands[2]))
4007     {
4008       emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
4009       DONE;
4010     }
4011 }")
4012
4013 (define_insn "*mulsidi3_sp32"
4014   [(set (match_operand:DI 0 "register_operand" "=r")
4015         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
4016                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
4017   "TARGET_HARD_MUL"
4018   "*
4019 {
4020   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
4021 }"
4022   [(set (attr "length")
4023         (if_then_else (eq_attr "isa" "sparclet")
4024                       (const_int 1) (const_int 2)))])
4025
4026 ;; Extra pattern, because sign_extend of a constant isn't valid.
4027
4028 (define_insn "const_mulsidi3"
4029   [(set (match_operand:DI 0 "register_operand" "=r")
4030         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
4031                  (match_operand:SI 2 "small_int" "I")))]
4032   "TARGET_HARD_MUL"
4033   "*
4034 {
4035   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
4036 }"
4037   [(set (attr "length")
4038         (if_then_else (eq_attr "isa" "sparclet")
4039                       (const_int 1) (const_int 2)))])
4040
4041 (define_expand "smulsi3_highpart"
4042   [(set (match_operand:SI 0 "register_operand" "")
4043         (truncate:SI
4044          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
4045                                (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
4046                       (const_int 32))))]
4047   "TARGET_HARD_MUL"
4048   "
4049 {
4050   if (CONSTANT_P (operands[2]))
4051     {
4052       emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
4053       DONE;
4054     }
4055 }")
4056
4057 (define_insn "*smulsidi3_highpart_sp32"
4058   [(set (match_operand:SI 0 "register_operand" "=r")
4059         (truncate:SI
4060          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
4061                                (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
4062                       (const_int 32))))]
4063   "TARGET_HARD_MUL"
4064   "smul %1,%2,%%g0\;rd %%y,%0"
4065   [(set_attr "length" "2")])
4066
4067 (define_insn "const_smulsi3_highpart"
4068   [(set (match_operand:SI 0 "register_operand" "=r")
4069         (truncate:SI
4070          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
4071                                (match_operand:SI 2 "register_operand" "r"))
4072                       (const_int 32))))]
4073   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
4074   "smul %1,%2,%%g0\;rd %%y,%0"
4075   [(set_attr "length" "2")])
4076
4077 (define_expand "umulsidi3"
4078   [(set (match_operand:DI 0 "register_operand" "")
4079         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
4080                  (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
4081   "TARGET_HARD_MUL"
4082   "
4083 {
4084   if (CONSTANT_P (operands[2]))
4085     {
4086       emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
4087       DONE;
4088     }
4089 }")
4090
4091 (define_insn "*umulsidi3_sp32"
4092   [(set (match_operand:DI 0 "register_operand" "=r")
4093         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4094                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
4095   "TARGET_HARD_MUL"
4096   "*
4097 {
4098   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
4099 }"
4100   [(set (attr "length")
4101         (if_then_else (eq_attr "isa" "sparclet")
4102                       (const_int 1) (const_int 2)))])
4103
4104 ;; Extra pattern, because sign_extend of a constant isn't valid.
4105
4106 (define_insn "const_umulsidi3"
4107   [(set (match_operand:DI 0 "register_operand" "=r")
4108         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4109                  (match_operand:SI 2 "uns_small_int" "")))]
4110   "TARGET_HARD_MUL"
4111   "*
4112 {
4113   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
4114 }"
4115   [(set (attr "length")
4116         (if_then_else (eq_attr "isa" "sparclet")
4117                       (const_int 1) (const_int 2)))])
4118
4119 (define_expand "umulsi3_highpart"
4120   [(set (match_operand:SI 0 "register_operand" "")
4121         (truncate:SI
4122          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
4123                                (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
4124                       (const_int 32))))]
4125   "TARGET_HARD_MUL"
4126   "
4127 {
4128   if (CONSTANT_P (operands[2]))
4129     {
4130       emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
4131       DONE;
4132     }
4133 }")
4134
4135 (define_insn "*umulsidi3_highpart_sp32"
4136   [(set (match_operand:SI 0 "register_operand" "=r")
4137         (truncate:SI
4138          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4139                                (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
4140                       (const_int 32))))]
4141   "TARGET_HARD_MUL"
4142   "umul %1,%2,%%g0\;rd %%y,%0"
4143   [(set_attr "length" "2")])
4144
4145 (define_insn "const_umulsi3_highpart"
4146   [(set (match_operand:SI 0 "register_operand" "=r")
4147         (truncate:SI
4148          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4149                                (match_operand:SI 2 "uns_small_int" ""))
4150                       (const_int 32))))]
4151   "TARGET_HARD_MUL"
4152   "umul %1,%2,%%g0\;rd %%y,%0"
4153   [(set_attr "length" "2")])
4154
4155 ;; The v8 architecture specifies that there must be 3 instructions between
4156 ;; a y register write and a use of it for correct results.
4157
4158 (define_insn "divsi3"
4159   [(set (match_operand:SI 0 "register_operand" "=r")
4160         (div:SI (match_operand:SI 1 "register_operand" "r")
4161                 (match_operand:SI 2 "arith_operand" "rI")))
4162    (clobber (match_scratch:SI 3 "=&r"))]
4163   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
4164   "*
4165 {
4166   if (TARGET_V9)
4167     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\";
4168   else
4169     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\";
4170 }"
4171   [(set (attr "length")
4172         (if_then_else (eq_attr "isa" "v9")
4173                       (const_int 3) (const_int 6)))])
4174
4175 (define_insn "divdi3"
4176   [(set (match_operand:DI 0 "register_operand" "=r")
4177         (div:DI (match_operand:DI 1 "register_operand" "r")
4178                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4179   "TARGET_ARCH64"
4180   "sdivx %1,%2,%0")
4181
4182 ;; It is not known whether this will match.
4183
4184 (define_insn "*cmp_sdiv_cc_set"
4185   [(set (match_operand:SI 0 "register_operand" "=r")
4186         (div:SI (match_operand:SI 1 "register_operand" "r")
4187                 (match_operand:SI 2 "arith_operand" "rI")))
4188    (set (reg:CC 100)
4189         (compare:CC (div:SI (match_dup 1) (match_dup 2))
4190                     (const_int 0)))
4191    (clobber (match_scratch:SI 3 "=&r"))]
4192   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
4193   "*
4194 {
4195   if (TARGET_V9)
4196     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\";
4197   else
4198     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\";
4199 }"
4200   [(set (attr "length")
4201         (if_then_else (eq_attr "isa" "v9")
4202                       (const_int 3) (const_int 6)))])
4203
4204 (define_insn "udivsi3"
4205   [(set (match_operand:SI 0 "register_operand" "=r")
4206         (udiv:SI (match_operand:SI 1 "register_operand" "r")
4207                  (match_operand:SI 2 "arith_operand" "rI")))]
4208   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
4209   "*
4210 {
4211   if (TARGET_V9)
4212     return \"wr %%g0,%%g0,%%y\;udiv %1,%2,%0\";
4213   else
4214     return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0\";
4215 }"
4216   [(set (attr "length")
4217         (if_then_else (eq_attr "isa" "v9")
4218                       (const_int 2) (const_int 5)))])
4219
4220 (define_insn "udivdi3"
4221   [(set (match_operand:DI 0 "register_operand" "=r")
4222         (udiv:DI (match_operand:DI 1 "register_operand" "r")
4223                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
4224   "TARGET_ARCH64"
4225   "udivx %1,%2,%0")
4226
4227 ;; It is not known whether this will match.
4228
4229 (define_insn "*cmp_udiv_cc_set"
4230   [(set (match_operand:SI 0 "register_operand" "=r")
4231         (udiv:SI (match_operand:SI 1 "register_operand" "r")
4232                 (match_operand:SI 2 "arith_operand" "rI")))
4233    (set (reg:CC 100)
4234         (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
4235                     (const_int 0)))]
4236   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
4237   "*
4238 {
4239   if (TARGET_V9)
4240     return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\";
4241   else
4242     return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\";
4243 }"
4244   [(set (attr "length")
4245         (if_then_else (eq_attr "isa" "v9")
4246                       (const_int 2) (const_int 5)))])
4247
4248 ; sparclet multiply/accumulate insns
4249
4250 (define_insn "*smacsi"
4251   [(set (match_operand:SI 0 "register_operand" "=r")
4252         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
4253                           (match_operand:SI 2 "arith_operand" "rI"))
4254                  (match_operand:SI 3 "register_operand" "0")))]
4255   "TARGET_SPARCLET"
4256   "smac %1,%2,%0"
4257   [(set_attr "type" "imul")])
4258
4259 (define_insn "*smacdi"
4260   [(set (match_operand:DI 0 "register_operand" "=r")
4261         (plus:DI (mult:DI (sign_extend:DI
4262                            (match_operand:SI 1 "register_operand" "%r"))
4263                           (sign_extend:DI
4264                            (match_operand:SI 2 "register_operand" "r")))
4265                  (match_operand:DI 3 "register_operand" "0")))]
4266   "TARGET_SPARCLET"
4267   "smacd %1,%2,%L0"
4268   [(set_attr "type" "imul")])
4269
4270 (define_insn "*umacdi"
4271   [(set (match_operand:DI 0 "register_operand" "=r")
4272         (plus:DI (mult:DI (zero_extend:DI
4273                            (match_operand:SI 1 "register_operand" "%r"))
4274                           (zero_extend:DI
4275                            (match_operand:SI 2 "register_operand" "r")))
4276                  (match_operand:DI 3 "register_operand" "0")))]
4277   "TARGET_SPARCLET"
4278   "umacd %1,%2,%L0"
4279   [(set_attr "type" "imul")])
4280 \f
4281 ;;- Boolean instructions
4282 ;; We define DImode `and' so with DImode `not' we can get
4283 ;; DImode `andn'.  Other combinations are possible.
4284
4285 (define_expand "anddi3"
4286   [(set (match_operand:DI 0 "register_operand" "")
4287         (and:DI (match_operand:DI 1 "arith_double_operand" "")
4288                 (match_operand:DI 2 "arith_double_operand" "")))]
4289   ""
4290   "")
4291
4292 (define_insn "*anddi3_sp32"
4293   [(set (match_operand:DI 0 "register_operand" "=r,b")
4294         (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
4295                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
4296   "! TARGET_ARCH64"
4297   "*
4298 {
4299   rtx op2 = operands[2];
4300
4301   if (which_alternative == 1)
4302     return \"fand %1,%2,%0\";
4303
4304   if (GET_CODE (op2) == CONST_INT
4305       || GET_CODE (op2) == CONST_DOUBLE)
4306     {
4307       rtx xoperands[4];
4308       xoperands[0] = operands[0];
4309       xoperands[1] = operands[1];
4310       if (WORDS_BIG_ENDIAN)
4311         split_double (op2, &xoperands[2], &xoperands[3]);
4312       else
4313         split_double (op2, &xoperands[3], &xoperands[2]);
4314       output_asm_insn (\"and %L1,%3,%L0\;and %H1,%2,%H0\", xoperands);
4315       return \"\";
4316     }
4317   return \"and %1,%2,%0\;and %R1,%R2,%R0\";
4318 }"
4319   [(set_attr "length" "2,1")])
4320
4321 (define_insn "*anddi3_sp64"
4322   [(set (match_operand:DI 0 "register_operand" "=r")
4323         (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
4324                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4325   "TARGET_ARCH64"
4326   "and %1,%2,%0")
4327
4328 (define_insn "andsi3"
4329   [(set (match_operand:SI 0 "register_operand" "=r,d")
4330         (and:SI (match_operand:SI 1 "arith_operand" "%r,d")
4331                 (match_operand:SI 2 "arith_operand" "rI,d")))]
4332   ""
4333   "@
4334    and %1,%2,%0
4335    fands %1,%2,%0"
4336   [(set_attr "type" "ialu,fp")])
4337
4338 (define_split
4339   [(set (match_operand:SI 0 "register_operand" "")
4340         (and:SI (match_operand:SI 1 "register_operand" "")
4341                 (match_operand:SI 2 "" "")))
4342    (clobber (match_operand:SI 3 "register_operand" ""))]
4343   "GET_CODE (operands[2]) == CONST_INT
4344    && !SMALL_INT (operands[2])
4345    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4346   [(set (match_dup 3) (match_dup 4))
4347    (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
4348   "
4349 {
4350   operands[4] = GEN_INT (~INTVAL (operands[2]));
4351 }")
4352
4353 (define_insn "*and_not_di_sp32"
4354   [(set (match_operand:DI 0 "register_operand" "=r,b")
4355         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
4356                 (match_operand:DI 2 "register_operand" "r,b")))]
4357   "! TARGET_ARCH64"
4358   "@
4359    andn %2,%1,%0\;andn %R2,%R1,%R0
4360    fandnot1 %1,%2,%0"
4361   [(set_attr "length" "2,1")])
4362
4363 (define_insn "*and_not_di_sp64"
4364   [(set (match_operand:DI 0 "register_operand" "=r")
4365         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4366                 (match_operand:DI 2 "register_operand" "r")))]
4367   "TARGET_ARCH64"
4368   "andn %2,%1,%0")
4369
4370 (define_insn "*and_not_si"
4371   [(set (match_operand:SI 0 "register_operand" "=r,d")
4372         (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
4373                 (match_operand:SI 2 "register_operand" "r,d")))]
4374   ""
4375   "@
4376    andn %2,%1,%0
4377    fandnot1s %1,%2,%0"
4378   [(set_attr "type" "ialu,fp")])
4379
4380 (define_expand "iordi3"
4381   [(set (match_operand:DI 0 "register_operand" "")
4382         (ior:DI (match_operand:DI 1 "arith_double_operand" "")
4383                 (match_operand:DI 2 "arith_double_operand" "")))]
4384   ""
4385   "")
4386
4387 (define_insn "*iordi3_sp32"
4388   [(set (match_operand:DI 0 "register_operand" "=r,b")
4389         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
4390                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
4391   "! TARGET_ARCH64"
4392   "*
4393 {
4394   rtx op2 = operands[2];
4395
4396   if (which_alternative == 1)
4397     return \"for %1,%2,%0\";
4398
4399   if (GET_CODE (op2) == CONST_INT
4400       || GET_CODE (op2) == CONST_DOUBLE)
4401     {
4402       rtx xoperands[4];
4403       xoperands[0] = operands[0];
4404       xoperands[1] = operands[1];
4405       if (WORDS_BIG_ENDIAN)
4406         split_double (op2, &xoperands[2], &xoperands[3]);
4407       else
4408         split_double (op2, &xoperands[3], &xoperands[2]);
4409       output_asm_insn (\"or %L1,%3,%L0\;or %H1,%2,%H0\", xoperands);
4410       return \"\";
4411     }
4412   return \"or %1,%2,%0\;or %R1,%R2,%R0\";
4413 }"
4414   [(set_attr "length" "2,1")])
4415
4416 (define_insn "*iordi3_sp64"
4417   [(set (match_operand:DI 0 "register_operand" "=r")
4418         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
4419                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4420   "TARGET_ARCH64"
4421   "or %1,%2,%0")
4422
4423 (define_insn "iorsi3"
4424   [(set (match_operand:SI 0 "register_operand" "=r,d")
4425         (ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
4426                 (match_operand:SI 2 "arith_operand" "rI,d")))]
4427   ""
4428   "@
4429    or %1,%2,%0
4430    fors %1,%2,%0"
4431   [(set_attr "type" "ialu,fp")])
4432
4433 (define_split
4434   [(set (match_operand:SI 0 "register_operand" "")
4435         (ior:SI (match_operand:SI 1 "register_operand" "")
4436                 (match_operand:SI 2 "" "")))
4437    (clobber (match_operand:SI 3 "register_operand" ""))]
4438   "GET_CODE (operands[2]) == CONST_INT
4439    && !SMALL_INT (operands[2])
4440    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4441   [(set (match_dup 3) (match_dup 4))
4442    (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
4443   "
4444 {
4445   operands[4] = GEN_INT (~INTVAL (operands[2]));
4446 }")
4447
4448 (define_insn "*or_not_di_sp32"
4449   [(set (match_operand:DI 0 "register_operand" "=r,b")
4450         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
4451                 (match_operand:DI 2 "register_operand" "r,b")))]
4452   "! TARGET_ARCH64"
4453   "@
4454    orn %2,%1,%0\;orn %R2,%R1,%R0
4455    fornot1 %1,%2,%0"
4456   [(set_attr "length" "2,1")])
4457
4458 (define_insn "*or_not_di_sp64"
4459   [(set (match_operand:DI 0 "register_operand" "=r")
4460         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4461                 (match_operand:DI 2 "register_operand" "r")))]
4462   "TARGET_ARCH64"
4463   "orn %2,%1,%0")
4464
4465 (define_insn "*or_not_si"
4466   [(set (match_operand:SI 0 "register_operand" "=r,d")
4467         (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
4468                 (match_operand:SI 2 "register_operand" "r,d")))]
4469   ""
4470   "@
4471    orn %2,%1,%0
4472    fornot1s %1,%2,%0"
4473   [(set_attr "type" "ialu,fp")])
4474
4475 (define_expand "xordi3"
4476   [(set (match_operand:DI 0 "register_operand" "")
4477         (xor:DI (match_operand:DI 1 "arith_double_operand" "")
4478                 (match_operand:DI 2 "arith_double_operand" "")))]
4479   ""
4480   "")
4481
4482 (define_insn "*xorsi3_sp32"
4483   [(set (match_operand:DI 0 "register_operand" "=r,b")
4484         (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
4485                 (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
4486   "! TARGET_ARCH64"
4487   "*
4488 {
4489   rtx op2 = operands[2];
4490
4491   if (which_alternative == 1)
4492     return \"fxor %1,%2,%0\";
4493
4494   if (GET_CODE (op2) == CONST_INT
4495       || GET_CODE (op2) == CONST_DOUBLE)
4496     {
4497       rtx xoperands[4];
4498       xoperands[0] = operands[0];
4499       xoperands[1] = operands[1];
4500       if (WORDS_BIG_ENDIAN)
4501         split_double (op2, &xoperands[2], &xoperands[3]);
4502       else
4503         split_double (op2, &xoperands[3], &xoperands[2]);
4504       output_asm_insn (\"xor %L1,%3,%L0\;xor %H1,%2,%H0\", xoperands);
4505       return \"\";
4506     }
4507   return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
4508 }"
4509   [(set_attr "length" "2,1")])
4510
4511 (define_insn "*xordi3_sp64"
4512   [(set (match_operand:DI 0 "register_operand" "=r")
4513         (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ")
4514                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4515   "TARGET_ARCH64"
4516   "xor %r1,%2,%0")
4517
4518 (define_insn "xorsi3"
4519   [(set (match_operand:SI 0 "register_operand" "=r,d")
4520         (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
4521                 (match_operand:SI 2 "arith_operand" "rI,d")))]
4522   ""
4523   "@
4524    xor %r1,%2,%0
4525    fxors %1,%2,%0"
4526   [(set_attr "type" "ialu,fp")])
4527
4528 (define_split
4529   [(set (match_operand:SI 0 "register_operand" "")
4530         (xor:SI (match_operand:SI 1 "register_operand" "")
4531                 (match_operand:SI 2 "" "")))
4532    (clobber (match_operand:SI 3 "register_operand" ""))]
4533   "GET_CODE (operands[2]) == CONST_INT
4534    && !SMALL_INT (operands[2])
4535    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4536   [(set (match_dup 3) (match_dup 4))
4537    (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
4538   "
4539 {
4540   operands[4] = GEN_INT (~INTVAL (operands[2]));
4541 }")
4542
4543 (define_split
4544   [(set (match_operand:SI 0 "register_operand" "")
4545         (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
4546                         (match_operand:SI 2 "" ""))))
4547    (clobber (match_operand:SI 3 "register_operand" ""))]
4548   "GET_CODE (operands[2]) == CONST_INT
4549    && !SMALL_INT (operands[2])
4550    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4551   [(set (match_dup 3) (match_dup 4))
4552    (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
4553   "
4554 {
4555   operands[4] = GEN_INT (~INTVAL (operands[2]));
4556 }")
4557
4558 ;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
4559 ;; Combine now canonicalizes to the rightmost expression.
4560 (define_insn "*xor_not_di_sp32"
4561   [(set (match_operand:DI 0 "register_operand" "=r,b")
4562         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
4563                         (match_operand:DI 2 "register_operand" "r,b"))))]
4564   "! TARGET_ARCH64"
4565   "@
4566    xnor %1,%2,%0\;xnor %R1,%R2,%R0
4567    fxnor %1,%2,%0"
4568   [(set_attr "length" "2,1")
4569    (set_attr "type" "ialu,fp")])
4570
4571 (define_insn "*xor_not_di_sp64"
4572   [(set (match_operand:DI 0 "register_operand" "=r")
4573         (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
4574                         (match_operand:DI 2 "arith_double_operand" "rHI"))))]
4575   "TARGET_ARCH64"
4576   "xnor %r1,%2,%0"
4577   [(set_attr "type" "ialu")])
4578
4579 (define_insn "*xor_not_si"
4580   [(set (match_operand:SI 0 "register_operand" "=r,d")
4581         (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
4582                         (match_operand:SI 2 "arith_operand" "rI,d"))))]
4583   ""
4584   "@
4585    xnor %r1,%2,%0
4586    fxnors %1,%2,%0"
4587   [(set_attr "type" "ialu,fp")])
4588
4589 ;; These correspond to the above in the case where we also (or only)
4590 ;; want to set the condition code.  
4591
4592 (define_insn "*cmp_cc_arith_op"
4593   [(set (reg:CC 100)
4594         (compare:CC
4595          (match_operator:SI 2 "cc_arithop"
4596                             [(match_operand:SI 0 "arith_operand" "%r")
4597                              (match_operand:SI 1 "arith_operand" "rI")])
4598          (const_int 0)))]
4599   ""
4600   "%A2cc %0,%1,%%g0"
4601   [(set_attr "type" "compare")])
4602
4603 (define_insn "*cmp_ccx_arith_op"
4604   [(set (reg:CCX 100)
4605         (compare:CCX
4606          (match_operator:DI 2 "cc_arithop"
4607                             [(match_operand:DI 0 "arith_double_operand" "%r")
4608                              (match_operand:DI 1 "arith_double_operand" "rHI")])
4609          (const_int 0)))]
4610   "TARGET_ARCH64"
4611   "%A2cc %0,%1,%%g0"
4612   [(set_attr "type" "compare")])
4613
4614 (define_insn "*cmp_cc_arith_op_set"
4615   [(set (reg:CC 100)
4616         (compare:CC
4617          (match_operator:SI 3 "cc_arithop"
4618                             [(match_operand:SI 1 "arith_operand" "%r")
4619                              (match_operand:SI 2 "arith_operand" "rI")])
4620          (const_int 0)))
4621    (set (match_operand:SI 0 "register_operand" "=r")
4622         (match_dup 3))]
4623   ""
4624   "%A3cc %1,%2,%0")
4625
4626 (define_insn "*cmp_ccx_arith_op_set"
4627   [(set (reg:CCX 100)
4628         (compare:CCX
4629          (match_operator:DI 3 "cc_arithop"
4630                             [(match_operand:DI 1 "arith_double_operand" "%r")
4631                              (match_operand:DI 2 "arith_double_operand" "rHI")])
4632          (const_int 0)))
4633    (set (match_operand:DI 0 "register_operand" "=r")
4634         (match_dup 3))]
4635   "TARGET_ARCH64"
4636   "%A3cc %1,%2,%0")
4637
4638 (define_insn "*cmp_cc_xor_not"
4639   [(set (reg:CC 100)
4640         (compare:CC
4641          (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
4642                          (match_operand:SI 1 "arith_operand" "rI")))
4643          (const_int 0)))]
4644   ""
4645   "xnorcc %r0,%1,%%g0"
4646   [(set_attr "type" "compare")])
4647
4648 (define_insn "*cmp_ccx_xor_not"
4649   [(set (reg:CCX 100)
4650         (compare:CCX
4651          (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
4652                          (match_operand:DI 1 "arith_double_operand" "rHI")))
4653          (const_int 0)))]
4654   "TARGET_ARCH64"
4655   "xnorcc %r0,%1,%%g0"
4656   [(set_attr "type" "compare")])
4657
4658 (define_insn "*cmp_cc_xor_not_set"
4659   [(set (reg:CC 100)
4660         (compare:CC
4661          (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4662                          (match_operand:SI 2 "arith_operand" "rI")))
4663          (const_int 0)))
4664    (set (match_operand:SI 0 "register_operand" "=r")
4665         (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
4666   ""
4667   "xnorcc %r1,%2,%0")
4668
4669 (define_insn "*cmp_ccx_xor_not_set"
4670   [(set (reg:CCX 100)
4671         (compare:CCX
4672          (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
4673                          (match_operand:DI 2 "arith_double_operand" "rHI")))
4674          (const_int 0)))
4675    (set (match_operand:DI 0 "register_operand" "=r")
4676         (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
4677   "TARGET_ARCH64"
4678   "xnorcc %r1,%2,%0")
4679
4680 (define_insn "*cmp_cc_arith_op_not"
4681   [(set (reg:CC 100)
4682         (compare:CC
4683          (match_operator:SI 2 "cc_arithopn"
4684                             [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
4685                              (match_operand:SI 1 "reg_or_0_operand" "rJ")])
4686          (const_int 0)))]
4687   ""
4688   "%B2cc %r1,%0,%%g0"
4689   [(set_attr "type" "compare")])
4690
4691 (define_insn "*cmp_ccx_arith_op_not"
4692   [(set (reg:CCX 100)
4693         (compare:CCX
4694          (match_operator:DI 2 "cc_arithopn"
4695                             [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4696                              (match_operand:DI 1 "reg_or_0_operand" "rJ")])
4697          (const_int 0)))]
4698   "TARGET_ARCH64"
4699   "%B2cc %r1,%0,%%g0"
4700   [(set_attr "type" "compare")])
4701
4702 (define_insn "*cmp_cc_arith_op_not_set"
4703   [(set (reg:CC 100)
4704         (compare:CC
4705          (match_operator:SI 3 "cc_arithopn"
4706                             [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
4707                              (match_operand:SI 2 "reg_or_0_operand" "rJ")])
4708          (const_int 0)))
4709    (set (match_operand:SI 0 "register_operand" "=r")
4710         (match_dup 3))]
4711   ""
4712   "%B3cc %r2,%1,%0")
4713
4714 (define_insn "*cmp_ccx_arith_op_not_set"
4715   [(set (reg:CCX 100)
4716         (compare:CCX
4717          (match_operator:DI 3 "cc_arithopn"
4718                             [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4719                              (match_operand:DI 2 "reg_or_0_operand" "rJ")])
4720          (const_int 0)))
4721    (set (match_operand:DI 0 "register_operand" "=r")
4722         (match_dup 3))]
4723   "TARGET_ARCH64"
4724   "%B3cc %r2,%1,%0")
4725
4726 ;; We cannot use the "neg" pseudo insn because the Sun assembler
4727 ;; does not know how to make it work for constants.
4728
4729 (define_expand "negdi2"
4730   [(set (match_operand:DI 0 "register_operand" "=r")
4731         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4732   ""
4733   "
4734 {
4735   if (! TARGET_ARCH64)
4736     {
4737       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
4738                           gen_rtx (SET, VOIDmode, operand0,
4739                                    gen_rtx (NEG, DImode, operand1)),
4740                           gen_rtx (CLOBBER, VOIDmode,
4741                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
4742       DONE;
4743     }
4744 }")
4745
4746 (define_insn "*negdi2_sp32"
4747   [(set (match_operand:DI 0 "register_operand" "=r")
4748         (neg:DI (match_operand:DI 1 "register_operand" "r")))
4749    (clobber (reg:SI 100))]
4750   "! TARGET_ARCH64"
4751   "*
4752 {
4753   if (TARGET_LIVE_G0)
4754     output_asm_insn (\"and %%g0,0,%%g0\", operands);
4755   return \"subcc %%g0,%L1,%L0\;subx %%g0,%H1,%H0\";
4756 }"
4757   [(set_attr "type" "unary")
4758    ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical.
4759    (set_attr "length" "2")])
4760
4761 (define_insn "*negdi2_sp64"
4762   [(set (match_operand:DI 0 "register_operand" "=r")
4763         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4764   "TARGET_ARCH64"
4765   "sub %%g0,%1,%0"
4766   [(set_attr "type" "unary")
4767    (set_attr "length" "1")])
4768
4769 (define_insn "negsi2"
4770   [(set (match_operand:SI 0 "register_operand" "=r")
4771         (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
4772   ""
4773   "*
4774 {
4775   if (TARGET_LIVE_G0)
4776     return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\";
4777   return \"sub %%g0,%1,%0\";
4778 }"
4779   [(set_attr "type" "unary")
4780    (set (attr "length")
4781         (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1)))])
4782
4783 (define_insn "*cmp_cc_neg"
4784   [(set (reg:CC_NOOV 100)
4785         (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
4786                          (const_int 0)))]
4787   "! TARGET_LIVE_G0"
4788   "subcc %%g0,%0,%%g0"
4789   [(set_attr "type" "compare")])
4790
4791 (define_insn "*cmp_ccx_neg"
4792   [(set (reg:CCX_NOOV 100)
4793         (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4794                           (const_int 0)))]
4795   "TARGET_ARCH64"
4796   "subcc %%g0,%0,%%g0"
4797   [(set_attr "type" "compare")])
4798
4799 (define_insn "*cmp_cc_set_neg"
4800   [(set (reg:CC_NOOV 100)
4801         (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
4802                          (const_int 0)))
4803    (set (match_operand:SI 0 "register_operand" "=r")
4804         (neg:SI (match_dup 1)))]
4805   "! TARGET_LIVE_G0"
4806   "subcc %%g0,%1,%0"
4807   [(set_attr "type" "unary")])
4808
4809 (define_insn "*cmp_ccx_set_neg"
4810   [(set (reg:CCX_NOOV 100)
4811         (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4812                           (const_int 0)))
4813    (set (match_operand:DI 0 "register_operand" "=r")
4814         (neg:DI (match_dup 1)))]
4815   "TARGET_ARCH64"
4816   "subcc %%g0,%1,%0"
4817   [(set_attr "type" "unary")])
4818
4819 ;; We cannot use the "not" pseudo insn because the Sun assembler
4820 ;; does not know how to make it work for constants.
4821 (define_expand "one_cmpldi2"
4822   [(set (match_operand:DI 0 "register_operand" "")
4823         (not:DI (match_operand:DI 1 "register_operand" "")))]
4824   ""
4825   "")
4826
4827 (define_insn "*one_cmpldi2_sp32"
4828   [(set (match_operand:DI 0 "register_operand" "=r,b")
4829         (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
4830   "! TARGET_ARCH64"
4831   "@
4832    xnor %1,0,%0\;xnor %R1,0,%R0
4833    fnot1 %1,%0"
4834   [(set_attr "type" "unary,fp")
4835    (set_attr "length" "2,1")])
4836
4837 (define_insn "*one_cmpldi2_sp64"
4838   [(set (match_operand:DI 0 "register_operand" "=r")
4839         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
4840   "TARGET_ARCH64"
4841   "xnor %1,0,%0"
4842   [(set_attr "type" "unary")])
4843
4844 (define_insn "one_cmplsi2"
4845   [(set (match_operand:SI 0 "register_operand" "=r,r,d")
4846         (not:SI (match_operand:SI 1 "arith_operand" "r,I,d")))]
4847   ""
4848   "*
4849 {
4850   if (which_alternative == 0)
4851     return \"xnor %1,0,%0\";
4852   if (which_alternative == 1)
4853     return \"fnot1s %1,%0\";
4854   if (TARGET_LIVE_G0)
4855     output_asm_insn (\"and %%g0,0,%%g0\", operands);
4856   return \"xnor %%g0,%1,%0\";
4857 }"
4858   [(set_attr "type" "unary,unary,fp")
4859    (set_attr_alternative "length"
4860      [(const_int 1)
4861       (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))
4862       (const_int 1)])])
4863
4864 (define_insn "*cmp_cc_not"
4865   [(set (reg:CC 100)
4866         (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
4867                     (const_int 0)))]
4868   "! TARGET_LIVE_G0"
4869   "xnorcc %%g0,%0,%%g0"
4870   [(set_attr "type" "compare")])
4871
4872 (define_insn "*cmp_ccx_not"
4873   [(set (reg:CCX 100)
4874         (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4875                      (const_int 0)))]
4876   "TARGET_ARCH64"
4877   "xnorcc %%g0,%0,%%g0"
4878   [(set_attr "type" "compare")])
4879
4880 (define_insn "*cmp_cc_set_not"
4881   [(set (reg:CC 100)
4882         (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
4883                     (const_int 0)))
4884    (set (match_operand:SI 0 "register_operand" "=r")
4885         (not:SI (match_dup 1)))]
4886   "! TARGET_LIVE_G0"
4887   "xnorcc %%g0,%1,%0"
4888   [(set_attr "type" "unary")])
4889
4890 (define_insn "*cmp_ccx_set_not"
4891   [(set (reg:CCX 100)
4892         (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4893                     (const_int 0)))
4894    (set (match_operand:DI 0 "register_operand" "=r")
4895         (not:DI (match_dup 1)))]
4896   "TARGET_ARCH64"
4897   "xnorcc %%g0,%1,%0"
4898   [(set_attr "type" "unary")])
4899 \f
4900 ;; Floating point arithmetic instructions.
4901
4902 (define_insn "addtf3"
4903   [(set (match_operand:TF 0 "register_operand" "=e")
4904         (plus:TF (match_operand:TF 1 "register_operand" "e")
4905                  (match_operand:TF 2 "register_operand" "e")))]
4906   "TARGET_FPU && TARGET_HARD_QUAD"
4907   "faddq %1,%2,%0"
4908   [(set_attr "type" "fp")])
4909
4910 (define_insn "adddf3"
4911   [(set (match_operand:DF 0 "register_operand" "=e")
4912         (plus:DF (match_operand:DF 1 "register_operand" "e")
4913                  (match_operand:DF 2 "register_operand" "e")))]
4914   "TARGET_FPU"
4915   "faddd %1,%2,%0"
4916   [(set_attr "type" "fp")])
4917
4918 (define_insn "addsf3"
4919   [(set (match_operand:SF 0 "register_operand" "=f")
4920         (plus:SF (match_operand:SF 1 "register_operand" "f")
4921                  (match_operand:SF 2 "register_operand" "f")))]
4922   "TARGET_FPU"
4923   "fadds %1,%2,%0"
4924   [(set_attr "type" "fp")])
4925
4926 (define_insn "subtf3"
4927   [(set (match_operand:TF 0 "register_operand" "=e")
4928         (minus:TF (match_operand:TF 1 "register_operand" "e")
4929                   (match_operand:TF 2 "register_operand" "e")))]
4930   "TARGET_FPU && TARGET_HARD_QUAD"
4931   "fsubq %1,%2,%0"
4932   [(set_attr "type" "fp")])
4933
4934 (define_insn "subdf3"
4935   [(set (match_operand:DF 0 "register_operand" "=e")
4936         (minus:DF (match_operand:DF 1 "register_operand" "e")
4937                   (match_operand:DF 2 "register_operand" "e")))]
4938   "TARGET_FPU"
4939   "fsubd %1,%2,%0"
4940   [(set_attr "type" "fp")])
4941
4942 (define_insn "subsf3"
4943   [(set (match_operand:SF 0 "register_operand" "=f")
4944         (minus:SF (match_operand:SF 1 "register_operand" "f")
4945                   (match_operand:SF 2 "register_operand" "f")))]
4946   "TARGET_FPU"
4947   "fsubs %1,%2,%0"
4948   [(set_attr "type" "fp")])
4949
4950 (define_insn "multf3"
4951   [(set (match_operand:TF 0 "register_operand" "=e")
4952         (mult:TF (match_operand:TF 1 "register_operand" "e")
4953                  (match_operand:TF 2 "register_operand" "e")))]
4954   "TARGET_FPU && TARGET_HARD_QUAD"
4955   "fmulq %1,%2,%0"
4956   [(set_attr "type" "fpmul")])
4957
4958 (define_insn "muldf3"
4959   [(set (match_operand:DF 0 "register_operand" "=e")
4960         (mult:DF (match_operand:DF 1 "register_operand" "e")
4961                  (match_operand:DF 2 "register_operand" "e")))]
4962   "TARGET_FPU"
4963   "fmuld %1,%2,%0"
4964   [(set_attr "type" "fpmul")])
4965
4966 (define_insn "mulsf3"
4967   [(set (match_operand:SF 0 "register_operand" "=f")
4968         (mult:SF (match_operand:SF 1 "register_operand" "f")
4969                  (match_operand:SF 2 "register_operand" "f")))]
4970   "TARGET_FPU"
4971   "fmuls %1,%2,%0"
4972   [(set_attr "type" "fpmul")])
4973
4974 (define_insn "*muldf3_extend"
4975   [(set (match_operand:DF 0 "register_operand" "=e")
4976         (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
4977                  (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
4978   "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
4979   "fsmuld %1,%2,%0"
4980   [(set_attr "type" "fpmul")])
4981
4982 (define_insn "*multf3_extend"
4983   [(set (match_operand:TF 0 "register_operand" "=e")
4984         (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
4985                  (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
4986   "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
4987   "fdmulq %1,%2,%0"
4988   [(set_attr "type" "fpmul")])
4989
4990 ;; don't have timing for quad-prec. divide.
4991 (define_insn "divtf3"
4992   [(set (match_operand:TF 0 "register_operand" "=e")
4993         (div:TF (match_operand:TF 1 "register_operand" "e")
4994                 (match_operand:TF 2 "register_operand" "e")))]
4995   "TARGET_FPU && TARGET_HARD_QUAD"
4996   "fdivq %1,%2,%0"
4997   [(set_attr "type" "fpdivd")])
4998
4999 (define_insn "divdf3"
5000   [(set (match_operand:DF 0 "register_operand" "=e")
5001         (div:DF (match_operand:DF 1 "register_operand" "e")
5002                 (match_operand:DF 2 "register_operand" "e")))]
5003   "TARGET_FPU"
5004   "fdivd %1,%2,%0"
5005   [(set_attr "type" "fpdivd")])
5006
5007 (define_insn "divsf3"
5008   [(set (match_operand:SF 0 "register_operand" "=f")
5009         (div:SF (match_operand:SF 1 "register_operand" "f")
5010                 (match_operand:SF 2 "register_operand" "f")))]
5011   "TARGET_FPU"
5012   "fdivs %1,%2,%0"
5013   [(set_attr "type" "fpdivs")])
5014
5015 (define_insn "negtf2"
5016   [(set (match_operand:TF 0 "register_operand" "=e,e")
5017         (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
5018   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
5019   "TARGET_FPU"
5020   "*
5021 {
5022   /* v9: can't use fnegs, won't work with upper regs.  */
5023   if (which_alternative == 0)
5024    return TARGET_V9 ? \"fnegd %0,%0\" : \"fnegs %0,%0\";
5025   else
5026    return TARGET_V9 ? \"fnegd %1,%0\;fmovd %S1,%S0\"
5027      : \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
5028 }"
5029   [(set_attr "type" "fpmove")
5030    (set_attr_alternative "length"
5031      [(const_int 1)
5032       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
5033
5034 (define_insn "negdf2"
5035   [(set (match_operand:DF 0 "register_operand" "=e,e")
5036         (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
5037   "TARGET_FPU"
5038   "*
5039 {
5040   if (TARGET_V9)
5041     return \"fnegd %1,%0\";
5042   else if (which_alternative == 0)
5043    return \"fnegs %0,%0\";
5044   else
5045    return \"fnegs %1,%0\;fmovs %R1,%R0\";
5046 }"
5047   [(set_attr "type" "fpmove")
5048    (set_attr_alternative "length"
5049      [(const_int 1)
5050       (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
5051
5052 (define_insn "negsf2"
5053   [(set (match_operand:SF 0 "register_operand" "=f")
5054         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
5055   "TARGET_FPU"
5056   "fnegs %1,%0"
5057   [(set_attr "type" "fpmove")])
5058
5059 (define_insn "abstf2"
5060   [(set (match_operand:TF 0 "register_operand" "=e,e")
5061         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
5062   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
5063   "TARGET_FPU"
5064   "*
5065 {
5066   /* v9: can't use fabss, won't work with upper regs.  */
5067   if (which_alternative == 0)
5068     return TARGET_V9 ? \"fabsd %0,%0\" : \"fabss %0,%0\";
5069   else
5070     return TARGET_V9 ? \"fabsd %1,%0\;fmovd %S1,%S0\"
5071       : \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
5072 }"
5073   [(set_attr "type" "fpmove")
5074    (set_attr_alternative "length"
5075      [(const_int 1)
5076       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
5077
5078 (define_insn "absdf2"
5079   [(set (match_operand:DF 0 "register_operand" "=e,e")
5080         (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
5081   "TARGET_FPU"
5082   "*
5083 {
5084   if (TARGET_V9)
5085     return \"fabsd %1,%0\";
5086   else if (which_alternative == 0)
5087     return \"fabss %0,%0\";
5088   else
5089     return \"fabss %1,%0\;fmovs %R1,%R0\";
5090 }"
5091   [(set_attr "type" "fpmove")
5092    (set_attr_alternative "length"
5093      [(const_int 1)
5094       (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
5095
5096 (define_insn "abssf2"
5097   [(set (match_operand:SF 0 "register_operand" "=f")
5098         (abs:SF (match_operand:SF 1 "register_operand" "f")))]
5099   "TARGET_FPU"
5100   "fabss %1,%0"
5101   [(set_attr "type" "fpmove")])
5102
5103 (define_insn "sqrttf2"
5104   [(set (match_operand:TF 0 "register_operand" "=e")
5105         (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
5106   "TARGET_FPU && TARGET_HARD_QUAD"
5107   "fsqrtq %1,%0"
5108   [(set_attr "type" "fpsqrt")])
5109
5110 (define_insn "sqrtdf2"
5111   [(set (match_operand:DF 0 "register_operand" "=e")
5112         (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
5113   "TARGET_FPU"
5114   "fsqrtd %1,%0"
5115   [(set_attr "type" "fpsqrt")])
5116
5117 (define_insn "sqrtsf2"
5118   [(set (match_operand:SF 0 "register_operand" "=f")
5119         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
5120   "TARGET_FPU"
5121   "fsqrts %1,%0"
5122   [(set_attr "type" "fpsqrt")])
5123 \f
5124 ;;- arithmetic shift instructions
5125
5126 (define_insn "ashlsi3"
5127   [(set (match_operand:SI 0 "register_operand" "=r")
5128         (ashift:SI (match_operand:SI 1 "register_operand" "r")
5129                    (match_operand:SI 2 "arith_operand" "rI")))]
5130   ""
5131   "*
5132 {
5133   if (GET_CODE (operands[2]) == CONST_INT
5134       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
5135     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
5136
5137   return \"sll %1,%2,%0\";
5138 }"
5139   [(set_attr "type" "shift")])
5140
5141 (define_insn "ashldi3"
5142   [(set (match_operand:DI 0 "register_operand" "=r")
5143         (ashift:DI (match_operand:DI 1 "register_operand" "r")
5144                    (match_operand:SI 2 "arith_operand" "rI")))]
5145   "TARGET_ARCH64"
5146   "*
5147 {
5148   if (GET_CODE (operands[2]) == CONST_INT
5149       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
5150     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
5151
5152   return \"sllx %1,%2,%0\";
5153 }")
5154
5155 (define_insn "*cmp_cc_ashift_1"
5156   [(set (reg:CC_NOOV 100)
5157         (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
5158                                     (const_int 1))
5159                          (const_int 0)))]
5160   ""
5161   "addcc %0,%0,%%g0"
5162   [(set_attr "type" "compare")])
5163
5164 (define_insn "*cmp_cc_set_ashift_1"
5165   [(set (reg:CC_NOOV 100)
5166         (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
5167                                     (const_int 1))
5168                          (const_int 0)))
5169    (set (match_operand:SI 0 "register_operand" "=r")
5170         (ashift:SI (match_dup 1) (const_int 1)))]
5171   ""
5172   "addcc %1,%1,%0")
5173
5174 (define_insn "ashrsi3"
5175   [(set (match_operand:SI 0 "register_operand" "=r")
5176         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
5177                      (match_operand:SI 2 "arith_operand" "rI")))]
5178   ""
5179   "*
5180 {
5181   if (GET_CODE (operands[2]) == CONST_INT
5182       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
5183     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
5184
5185   return \"sra %1,%2,%0\";
5186 }"
5187   [(set_attr "type" "shift")])
5188
5189 (define_insn "ashrdi3"
5190   [(set (match_operand:DI 0 "register_operand" "=r")
5191         (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
5192                      (match_operand:SI 2 "arith_operand" "rI")))]
5193   "TARGET_ARCH64"
5194   "*
5195 {
5196   if (GET_CODE (operands[2]) == CONST_INT
5197       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
5198     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
5199
5200   return \"srax %1,%2,%0\";
5201 }")
5202
5203 (define_insn "lshrsi3"
5204   [(set (match_operand:SI 0 "register_operand" "=r")
5205         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
5206                      (match_operand:SI 2 "arith_operand" "rI")))]
5207   ""
5208   "*
5209 {
5210   if (GET_CODE (operands[2]) == CONST_INT
5211       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
5212     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
5213
5214   return \"srl %1,%2,%0\";
5215 }"
5216   [(set_attr "type" "shift")])
5217
5218 (define_insn "lshrdi3"
5219   [(set (match_operand:DI 0 "register_operand" "=r")
5220         (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
5221                      (match_operand:SI 2 "arith_operand" "rI")))]
5222   "TARGET_ARCH64"
5223   "*
5224 {
5225   if (GET_CODE (operands[2]) == CONST_INT
5226       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
5227     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
5228
5229   return \"srlx %1,%2,%0\";
5230 }")
5231 \f
5232 ;; Unconditional and other jump instructions
5233 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
5234 ;; following insn is never executed.  This saves us a nop.  Dbx does not
5235 ;; handle such branches though, so we only use them when optimizing.
5236 (define_insn "jump"
5237   [(set (pc) (label_ref (match_operand 0 "" "")))]
5238   ""
5239   "*
5240 {
5241   /* Some implementations are reported to have problems with
5242         foo: b,a foo
5243      i.e. an empty loop with the annul bit set.  The workaround is to use 
5244         foo: b foo; nop
5245      instead.  */
5246
5247   if (flag_delayed_branch
5248       && (insn_addresses[INSN_UID (operands[0])]
5249           == insn_addresses[INSN_UID (insn)]))
5250     return \"b %l0%#\";
5251   else
5252     return \"b%* %l0%(\";
5253 }"
5254   [(set_attr "type" "uncond_branch")])
5255
5256 (define_expand "tablejump"
5257   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
5258               (use (label_ref (match_operand 1 "" "")))])]
5259   ""
5260   "
5261 {
5262   if (GET_MODE (operands[0]) != Pmode)
5263     abort ();
5264
5265   /* We need to use the PC value in %o7 that was set up when the address
5266      of the label was loaded into a register, so we need different RTL.  */
5267   if (flag_pic)
5268     {
5269       if (!TARGET_PTR64)
5270         emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1]));
5271       else
5272         emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1]));
5273       DONE;
5274     }
5275 }")
5276
5277 (define_insn "pic_tablejump_32"
5278   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
5279    (use (label_ref (match_operand 1 "" "")))
5280    (use (reg:SI 15))]
5281   "! TARGET_PTR64"
5282   "jmp %%o7+%0%#"
5283   [(set_attr "type" "uncond_branch")])
5284
5285 (define_insn "pic_tablejump_64"
5286   [(set (pc) (match_operand:DI 0 "register_operand" "r"))
5287    (use (label_ref (match_operand 1 "" "")))
5288    (use (reg:DI 15))]
5289   "TARGET_PTR64"
5290   "jmp %%o7+%0%#"
5291   [(set_attr "type" "uncond_branch")])
5292
5293 (define_insn "*tablejump_sp32"
5294   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
5295    (use (label_ref (match_operand 1 "" "")))]
5296   "! TARGET_PTR64"
5297   "jmp %a0%#"
5298   [(set_attr "type" "uncond_branch")])
5299
5300 (define_insn "*tablejump_sp64"
5301   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
5302    (use (label_ref (match_operand 1 "" "")))]
5303   "TARGET_PTR64"
5304   "jmp %a0%#"
5305   [(set_attr "type" "uncond_branch")])
5306
5307 ;; This pattern recognizes the "instruction" that appears in 
5308 ;; a function call that wants a structure value, 
5309 ;; to inform the called function if compiled with Sun CC.
5310 ;(define_insn "*unimp_insn"
5311 ;  [(match_operand:SI 0 "immediate_operand" "")]
5312 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
5313 ;  "unimp %0"
5314 ;  [(set_attr "type" "marker")])
5315
5316 ;;- jump to subroutine
5317 (define_expand "call"
5318   ;; Note that this expression is not used for generating RTL.
5319   ;; All the RTL is generated explicitly below.
5320   [(call (match_operand 0 "call_operand" "")
5321          (match_operand 3 "" "i"))]
5322   ;; operands[2] is next_arg_register
5323   ;; operands[3] is struct_value_size_rtx.
5324   ""
5325   "
5326 {
5327   rtx fn_rtx, nregs_rtx;
5328
5329    if (GET_MODE (operands[0]) != FUNCTION_MODE)
5330     abort ();
5331
5332   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
5333     {
5334       /* This is really a PIC sequence.  We want to represent
5335          it as a funny jump so it's delay slots can be filled. 
5336
5337          ??? But if this really *is* a CALL, will not it clobber the
5338          call-clobbered registers?  We lose this if it is a JUMP_INSN.
5339          Why cannot we have delay slots filled if it were a CALL?  */
5340
5341       if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
5342         emit_jump_insn
5343           (gen_rtx (PARALLEL, VOIDmode,
5344                     gen_rtvec (3,
5345                                gen_rtx (SET, VOIDmode, pc_rtx,
5346                                         XEXP (operands[0], 0)),
5347                                GEN_INT (INTVAL (operands[3]) & 0xfff),
5348                                gen_rtx (CLOBBER, VOIDmode,
5349                                         gen_rtx (REG, Pmode, 15)))));
5350       else
5351         emit_jump_insn
5352           (gen_rtx (PARALLEL, VOIDmode,
5353                     gen_rtvec (2,
5354                                gen_rtx (SET, VOIDmode, pc_rtx,
5355                                         XEXP (operands[0], 0)),
5356                                gen_rtx (CLOBBER, VOIDmode,
5357                                         gen_rtx (REG, Pmode, 15)))));
5358       goto finish_call;
5359     }
5360
5361   fn_rtx = operands[0];
5362
5363   /* Count the number of parameter registers being used by this call.
5364      if that argument is NULL, it means we are using them all, which
5365      means 6 on the sparc.  */
5366 #if 0
5367   if (operands[2])
5368     nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
5369   else
5370     nregs_rtx = GEN_INT (6);
5371 #else
5372   nregs_rtx = const0_rtx;
5373 #endif
5374
5375   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
5376     emit_call_insn
5377       (gen_rtx (PARALLEL, VOIDmode,
5378                 gen_rtvec (3, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
5379                            GEN_INT (INTVAL (operands[3]) & 0xfff),
5380                            gen_rtx (CLOBBER, VOIDmode,
5381                                     gen_rtx (REG, Pmode, 15)))));
5382   else
5383     emit_call_insn
5384       (gen_rtx (PARALLEL, VOIDmode,
5385                 gen_rtvec (2, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
5386                            gen_rtx (CLOBBER, VOIDmode,
5387                                     gen_rtx (REG, Pmode, 15)))));
5388
5389  finish_call:
5390 #if 0
5391   /* If this call wants a structure value,
5392      emit an unimp insn to let the called function know about this.  */
5393   if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
5394     {
5395       rtx insn = emit_insn (operands[3]);
5396       SCHED_GROUP_P (insn) = 1;
5397     }
5398 #endif
5399
5400   DONE;
5401 }")
5402
5403 ;; We can't use the same pattern for these two insns, because then registers
5404 ;; in the address may not be properly reloaded.
5405
5406 (define_insn "*call_address_sp32"
5407   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5408          (match_operand 1 "" ""))
5409    (clobber (reg:SI 15))]
5410   ;;- Do not use operand 1 for most machines.
5411   "! TARGET_PTR64"
5412   "call %a0,%1%#"
5413   [(set_attr "type" "call")])
5414
5415 (define_insn "*call_symbolic_sp32"
5416   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5417          (match_operand 1 "" ""))
5418    (clobber (reg:SI 15))]
5419   ;;- Do not use operand 1 for most machines.
5420   "! TARGET_PTR64"
5421   "call %a0,%1%#"
5422   [(set_attr "type" "call")])
5423
5424 (define_insn "*call_address_sp64"
5425   [(call (mem:SI (match_operand:DI 0 "address_operand" "p"))
5426          (match_operand 1 "" ""))
5427    (clobber (reg:DI 15))]
5428   ;;- Do not use operand 1 for most machines.
5429   "TARGET_PTR64"
5430   "call %a0,%1%#"
5431   [(set_attr "type" "call")])
5432
5433 (define_insn "*call_symbolic_sp64"
5434   [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s"))
5435          (match_operand 1 "" ""))
5436    (clobber (reg:DI 15))]
5437   ;;- Do not use operand 1 for most machines.
5438   "TARGET_PTR64"
5439   "call %a0,%1%#"
5440   [(set_attr "type" "call")])
5441
5442 ;; This is a call that wants a structure value.
5443 ;; There is no such critter for v9 (??? we may need one anyway).
5444 (define_insn "*call_address_struct_value_sp32"
5445   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5446          (match_operand 1 "" ""))
5447    (match_operand 2 "immediate_operand" "")
5448    (clobber (reg:SI 15))]
5449   ;;- Do not use operand 1 for most machines.
5450   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
5451   "call %a0,%1\;nop\;unimp %2"
5452   [(set_attr "type" "call_no_delay_slot")])
5453
5454 ;; This is a call that wants a structure value.
5455 ;; There is no such critter for v9 (??? we may need one anyway).
5456 (define_insn "*call_symbolic_struct_value_sp32"
5457   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5458          (match_operand 1 "" ""))
5459    (match_operand 2 "immediate_operand" "")
5460    (clobber (reg:SI 15))]
5461   ;;- Do not use operand 1 for most machines.
5462   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
5463   "call %a0,%1\;nop\;unimp %2"
5464   [(set_attr "type" "call_no_delay_slot")])
5465
5466 ;; This is a call that may want a structure value.  This is used for
5467 ;; untyped_calls.
5468 (define_insn "*call_address_untyped_struct_value_sp32"
5469   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5470          (match_operand 1 "" ""))
5471    (match_operand 2 "immediate_operand" "")
5472    (clobber (reg:SI 15))]
5473   ;;- Do not use operand 1 for most machines.
5474   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
5475   "call %a0,%1\;nop\;nop"
5476   [(set_attr "type" "call_no_delay_slot")])
5477
5478 ;; This is a call that wants a structure value.
5479 (define_insn "*call_symbolic_untyped_struct_value_sp32"
5480   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5481          (match_operand 1 "" ""))
5482    (match_operand 2 "immediate_operand" "")
5483    (clobber (reg:SI 15))]
5484   ;;- Do not use operand 1 for most machines.
5485   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
5486   "call %a0,%1\;nop\;nop"
5487   [(set_attr "type" "call_no_delay_slot")])
5488
5489 (define_expand "call_value"
5490   ;; Note that this expression is not used for generating RTL.
5491   ;; All the RTL is generated explicitly below.
5492   [(set (match_operand 0 "register_operand" "=rf")
5493         (call (match_operand:SI 1 "" "")
5494               (match_operand 4 "" "")))]
5495   ;; operand 2 is stack_size_rtx
5496   ;; operand 3 is next_arg_register
5497   ""
5498   "
5499 {
5500   rtx fn_rtx, nregs_rtx;
5501   rtvec vec;
5502
5503   if (GET_MODE (operands[1]) != FUNCTION_MODE)
5504     abort ();
5505
5506   fn_rtx = operands[1];
5507
5508 #if 0
5509   if (operands[3])
5510     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
5511   else
5512     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
5513 #else
5514   nregs_rtx = const0_rtx;
5515 #endif
5516
5517   vec = gen_rtvec (2,
5518                    gen_rtx (SET, VOIDmode, operands[0],
5519                             gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
5520                    gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 15)));
5521
5522   emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
5523
5524   DONE;
5525 }")
5526
5527 (define_insn "*call_value_address_sp32"
5528   [(set (match_operand 0 "" "=rf")
5529         (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
5530               (match_operand 2 "" "")))
5531    (clobber (reg:SI 15))]
5532   ;;- Do not use operand 2 for most machines.
5533   "! TARGET_PTR64"
5534   "call %a1,%2%#"
5535   [(set_attr "type" "call")])
5536
5537 (define_insn "*call_value_symbolic_sp32"
5538   [(set (match_operand 0 "" "=rf")
5539         (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
5540               (match_operand 2 "" "")))
5541    (clobber (reg:SI 15))]
5542   ;;- Do not use operand 2 for most machines.
5543   "! TARGET_PTR64"
5544   "call %a1,%2%#"
5545   [(set_attr "type" "call")])
5546
5547 (define_insn "*call_value_address_sp64"
5548   [(set (match_operand 0 "" "=rf")
5549         (call (mem:SI (match_operand:DI 1 "address_operand" "p"))
5550               (match_operand 2 "" "")))
5551    (clobber (reg:DI 15))]
5552   ;;- Do not use operand 2 for most machines.
5553   "TARGET_PTR64"
5554   "call %a1,%2%#"
5555   [(set_attr "type" "call")])
5556
5557 (define_insn "*call_value_symbolic_sp64"
5558   [(set (match_operand 0 "" "=rf")
5559         (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s"))
5560               (match_operand 2 "" "")))
5561    (clobber (reg:DI 15))]
5562   ;;- Do not use operand 2 for most machines.
5563   "TARGET_PTR64"
5564   "call %a1,%2%#"
5565   [(set_attr "type" "call")])
5566
5567 (define_expand "untyped_call"
5568   [(parallel [(call (match_operand 0 "" "")
5569                     (const_int 0))
5570               (match_operand 1 "" "")
5571               (match_operand 2 "" "")])]
5572   ""
5573   "
5574 {
5575   int i;
5576
5577   /* Pass constm1 to indicate that it may expect a structure value, but
5578      we don't know what size it is.  */
5579   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
5580
5581   for (i = 0; i < XVECLEN (operands[2], 0); i++)
5582     {
5583       rtx set = XVECEXP (operands[2], 0, i);
5584       emit_move_insn (SET_DEST (set), SET_SRC (set));
5585     }
5586
5587   /* The optimizer does not know that the call sets the function value
5588      registers we stored in the result block.  We avoid problems by
5589      claiming that all hard registers are used and clobbered at this
5590      point.  */
5591   emit_insn (gen_blockage ());
5592
5593   DONE;
5594 }")
5595
5596 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5597 ;; all of memory.  This blocks insns from being moved across this point.
5598
5599 (define_insn "blockage"
5600   [(unspec_volatile [(const_int 0)] 0)]
5601   ""
5602   "")
5603
5604 ;; Prepare to return any type including a structure value.
5605
5606 (define_expand "untyped_return"
5607   [(match_operand:BLK 0 "memory_operand" "")
5608    (match_operand 1 "" "")]
5609   ""
5610   "
5611 {
5612   rtx valreg1 = gen_rtx (REG, DImode, 24);
5613   rtx valreg2 = gen_rtx (REG, TARGET_ARCH64 ? TFmode : DFmode, 32);
5614   rtx result = operands[0];
5615
5616   if (! TARGET_ARCH64)
5617     {
5618       rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
5619       rtx value = gen_reg_rtx (SImode);
5620
5621       /* Fetch the instruction where we will return to and see if it's an unimp
5622          instruction (the most significant 10 bits will be zero).  If so,
5623          update the return address to skip the unimp instruction.  */
5624       emit_move_insn (value,
5625                       gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
5626       emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
5627       emit_insn (gen_update_return (rtnreg, value));
5628     }
5629
5630   /* Reload the function value registers.  */
5631   emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
5632   emit_move_insn (valreg2,
5633                   change_address (result, TARGET_ARCH64 ? TFmode : DFmode,
5634                                   plus_constant (XEXP (result, 0), 8)));
5635
5636   /* Put USE insns before the return.  */
5637   emit_insn (gen_rtx (USE, VOIDmode, valreg1));
5638   emit_insn (gen_rtx (USE, VOIDmode, valreg2));
5639
5640   /* Construct the return.  */
5641   expand_null_return ();
5642
5643   DONE;
5644 }")
5645
5646 ;; This is a bit of a hack.  We're incrementing a fixed register (%i7),
5647 ;; and parts of the compiler don't want to believe that the add is needed.
5648
5649 (define_insn "update_return"
5650   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
5651                (match_operand:SI 1 "register_operand" "r")] 1)]
5652   "! TARGET_ARCH64"
5653   "cmp %1,0\;be,a .+8\;add %0,4,%0"
5654   [(set_attr "type" "multi")])
5655 \f
5656 (define_insn "return"
5657   [(return)
5658    (use (reg:SI 31))]
5659   "! TARGET_EPILOGUE"
5660   "* return output_return (operands);"
5661   [(set_attr "type" "multi")])
5662
5663 (define_insn "nop"
5664   [(const_int 0)]
5665   ""
5666   "nop")
5667
5668 (define_expand "indirect_jump"
5669   [(set (pc) (match_operand 0 "address_operand" "p"))]
5670   ""
5671   "")
5672
5673 (define_insn "*branch_sp32"
5674   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
5675   "! TARGET_PTR64"
5676  "jmp %a0%#"
5677  [(set_attr "type" "uncond_branch")])
5678  
5679 (define_insn "*branch_sp64"
5680   [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
5681   "TARGET_PTR64"
5682   "jmp %a0%#"
5683   [(set_attr "type" "uncond_branch")])
5684
5685 ;; ??? Doesn't work with -mflat.
5686 (define_expand "nonlocal_goto"
5687   [(match_operand:SI 0 "" "")
5688    (match_operand:SI 1 "general_operand" "")
5689    (match_operand:SI 2 "general_operand" "")
5690    (match_operand:SI 3 "general_operand" "")]
5691   ""
5692   "
5693 {
5694   rtx chain = operands[0];
5695   rtx fp = operands[1];
5696   rtx stack = operands[2];
5697   rtx lab = operands[3];
5698
5699   /* Trap instruction to flush all the register windows.  */
5700   emit_insn (gen_flush_register_windows ());
5701
5702   /* Load the fp value for the containing fn into %fp.  This is needed
5703      because STACK refers to %fp.  Note that virtual register instantiation
5704      fails if the virtual %fp isn't set from a register.  */
5705   if (GET_CODE (fp) != REG)
5706     fp = force_reg (Pmode, fp);
5707   emit_move_insn (virtual_stack_vars_rtx, fp);
5708
5709   /* Find the containing function's current nonlocal goto handler,
5710      which will do any cleanups and then jump to the label.  */
5711   emit_move_insn (gen_rtx (REG, Pmode, 8), lab);
5712
5713   /* Restore %fp from stack pointer value for containing function.
5714      The restore insn that follows will move this to %sp,
5715      and reload the appropriate value into %fp.  */
5716   emit_move_insn (frame_pointer_rtx, stack);
5717
5718   /* Put in the static chain register the nonlocal label address.  */
5719   emit_move_insn (static_chain_rtx, chain);
5720
5721   /* USE of frame_pointer_rtx added for consistency; not clear if
5722      really needed.  */
5723   emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
5724   emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
5725   emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
5726   /* Return, restoring reg window and jumping to goto handler.  */
5727   emit_insn (gen_goto_handler_and_restore ());
5728   emit_barrier ();
5729   DONE;
5730 }")
5731
5732 ;; Special trap insn to flush register windows.
5733 (define_insn "flush_register_windows"
5734   [(unspec_volatile [(const_int 0)] 1)]
5735   ""
5736   ;; ??? Use TARGET_V9 instead?
5737   "* return TARGET_ARCH64 ? \"flushw\" : \"ta 3\";"
5738   [(set_attr "type" "misc")])
5739
5740 (define_insn "goto_handler_and_restore"
5741   [(unspec_volatile [(const_int 0)] 2)
5742    (use (reg:SI 8))]
5743   ""
5744   "jmp %%o0+0\;restore"
5745   [(set_attr "type" "misc")
5746    (set_attr "length" "2")])
5747
5748 ;; Implement setjmp.  Step one, set up the buffer.
5749
5750 (define_expand "builtin_setjmp_setup"
5751   [(unspec [(match_operand 0 "" "")] 3)]
5752   ""
5753   "
5754 {
5755   if (TARGET_ARCH64)
5756     emit_insn (gen_setjmp_64 ());
5757   else
5758     emit_insn (gen_setjmp_32 ());
5759   DONE;
5760 }")
5761
5762 (define_expand "setjmp_32"
5763   [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
5764    (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
5765   ""
5766   "
5767 { operands[0] = frame_pointer_rtx; }")
5768
5769 (define_expand "setjmp_64"
5770   [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
5771    (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
5772   ""
5773   "
5774 { operands[0] = frame_pointer_rtx; }")
5775
5776 ;; Special pattern for the FLUSH instruction.
5777
5778 (define_insn "flush"
5779   [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)]
5780   ""
5781   "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
5782   [(set_attr "type" "misc")])
5783 \f
5784 ;; find first set.
5785
5786 ;; The scan instruction searches from the most significant bit while ffs
5787 ;; searches from the least significant bit.  The bit index and treatment of
5788 ;; zero also differ.  It takes at least 7 instructions to get the proper
5789 ;; result.  Here is an obvious 8 instruction sequence.
5790
5791 (define_insn "ffssi2"
5792   [(set (match_operand:SI 0 "register_operand" "=&r")
5793         (ffs:SI (match_operand:SI 1 "register_operand" "r")))
5794    (clobber (match_scratch:SI 2 "=&r"))]
5795   "TARGET_SPARCLITE || TARGET_SPARCLET"
5796   "*
5797 {
5798   if (TARGET_LIVE_G0)
5799     output_asm_insn (\"and %%g0,0,%%g0\", operands);
5800   return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\";
5801 }"
5802   [(set_attr "type" "multi")
5803    (set_attr "length" "8")])
5804
5805 ;; ??? This should be a define expand, so that the extra instruction have
5806 ;; a chance of being optimized away.
5807
5808 (define_insn "ffsdi2"
5809   [(set (match_operand:DI 0 "register_operand" "=&r")
5810         (ffs:DI (match_operand:DI 1 "register_operand" "r")))
5811    (clobber (match_scratch:DI 2 "=&r"))]
5812   "TARGET_ARCH64"
5813   "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,0,%0"
5814   [(set_attr "type" "multi")
5815    (set_attr "length" "5")])
5816 \f
5817 ;; Split up troublesome insns for better scheduling.  */
5818
5819 ;; The following patterns are straightforward.  They can be applied
5820 ;; either before or after register allocation.
5821
5822 (define_split
5823   [(set (match_operand 0 "splittable_symbolic_memory_operand" "")
5824         (match_operand 1 "reg_or_0_operand" ""))
5825    (clobber (match_operand:SI 2 "register_operand" ""))]
5826   "! flag_pic"
5827   [(set (match_dup 2) (high:SI (match_dup 3)))
5828    (set (match_dup 4) (match_dup 1))]
5829   "
5830 {
5831   operands[3] = XEXP (operands[0], 0);
5832   operands[4] = gen_rtx (MEM, GET_MODE (operands[0]),
5833                          gen_rtx (LO_SUM, SImode, operands[2], operands[3]));
5834   MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]);
5835   MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]);
5836   RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]);
5837 }")
5838
5839 (define_split
5840   [(set (match_operand 0 "splittable_immediate_memory_operand" "")
5841         (match_operand 1 "general_operand" ""))
5842    (clobber (match_operand:SI 2 "register_operand" ""))]
5843   "flag_pic"
5844   [(set (match_dup 3) (match_dup 1))]
5845   "
5846 {
5847   rtx addr = legitimize_pic_address (XEXP (operands[0], 0),
5848                                      GET_MODE (operands[0]),
5849                                      operands[2]);
5850   operands[3] = gen_rtx (MEM, GET_MODE (operands[0]), addr);
5851   MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]);
5852   MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]);
5853   RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]);
5854 }")
5855
5856 (define_split
5857   [(set (match_operand 0 "register_operand" "")
5858         (match_operand 1 "splittable_immediate_memory_operand" ""))]
5859   "flag_pic"
5860   [(set (match_dup 0) (match_dup 2))]
5861   "
5862 {
5863   rtx addr = legitimize_pic_address (XEXP (operands[1], 0),
5864                                      GET_MODE (operands[1]),
5865                                      operands[0]);
5866   operands[2] = gen_rtx (MEM, GET_MODE (operands[1]), addr);
5867   MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
5868   MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
5869   RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
5870 }")
5871
5872 ;; Sign- and Zero-extend operations can have symbolic memory operands.
5873
5874 (define_split
5875   [(set (match_operand 0 "register_operand" "")
5876         (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))]
5877   "flag_pic"
5878   [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))]
5879   "
5880 {
5881   rtx addr = legitimize_pic_address (XEXP (operands[2], 0),
5882                                      GET_MODE (operands[2]),
5883                                      operands[0]);
5884   operands[3] = gen_rtx (MEM, GET_MODE (operands[2]), addr);
5885   MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]);
5886   MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]);
5887   RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]);
5888 }")
5889
5890 (define_split
5891   [(set (match_operand:SI 0 "register_operand" "")
5892         (match_operand:SI 1 "immediate_operand" ""))]
5893   "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5894                   || GET_CODE (operands[1]) == CONST
5895                   || GET_CODE (operands[1]) == LABEL_REF)"
5896   [(set (match_dup 0) (high:SI (match_dup 1)))
5897    (set (match_dup 0)
5898         (lo_sum:SI (match_dup 0) (match_dup 1)))]
5899   "")
5900
5901 ;; LABEL_REFs are not modified by `legitimize_pic_address'
5902 ;; so do not recurse infinitely in the PIC case.
5903 (define_split
5904   [(set (match_operand:SI 0 "register_operand" "")
5905         (match_operand:SI 1 "immediate_operand" ""))]
5906   "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5907                 || GET_CODE (operands[1]) == CONST)"
5908   [(set (match_dup 0) (match_dup 1))]
5909   "
5910 {
5911   operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]);
5912 }")
5913 \f
5914 ;; These split sne/seq insns.  The forms of the resulting insns are 
5915 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
5916 ;; Nothing will look at these in detail after splitting has occurred.
5917
5918 ;; ??? v9 DImode versions are missing because addc and subc use %icc.
5919
5920 (define_split
5921   [(set (match_operand:SI 0 "register_operand" "")
5922         (ne:SI (match_operand:SI 1 "register_operand" "")
5923                (const_int 0)))
5924    (clobber (reg:CC 100))]
5925   ""
5926   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5927                                            (const_int 0)))
5928    (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
5929   "")
5930
5931 (define_split
5932   [(set (match_operand:SI 0 "register_operand" "")
5933         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5934                        (const_int 0))))
5935    (clobber (reg:CC 100))]
5936   ""
5937   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5938                                            (const_int 0)))
5939    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
5940   "")
5941
5942 (define_split
5943   [(set (match_operand:SI 0 "register_operand" "")
5944         (eq:SI (match_operand:SI 1 "register_operand" "")
5945                (const_int 0)))
5946    (clobber (reg:CC 100))]
5947   ""
5948   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5949                                            (const_int 0)))
5950    (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
5951   "")
5952
5953 (define_split
5954   [(set (match_operand:SI 0 "register_operand" "")
5955         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5956                        (const_int 0))))
5957    (clobber (reg:CC 100))]
5958   ""
5959   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5960                                            (const_int 0)))
5961    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
5962   "")
5963
5964 (define_split
5965   [(set (match_operand:SI 0 "register_operand" "")
5966         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5967                         (const_int 0))
5968                  (match_operand:SI 2 "register_operand" "")))
5969    (clobber (reg:CC 100))]
5970   ""
5971   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5972                                            (const_int 0)))
5973    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
5974                                (match_dup 2)))]
5975   "")
5976
5977 (define_split
5978   [(set (match_operand:SI 0 "register_operand" "")
5979         (minus:SI (match_operand:SI 2 "register_operand" "")
5980                   (ne:SI (match_operand:SI 1 "register_operand" "")
5981                          (const_int 0))))
5982    (clobber (reg:CC 100))]
5983   ""
5984   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5985                                            (const_int 0)))
5986    (set (match_dup 0) (minus:SI (match_dup 2)
5987                                 (ltu:SI (reg:CC 100) (const_int 0))))]
5988   "")
5989
5990 (define_split
5991   [(set (match_operand:SI 0 "register_operand" "")
5992         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5993                         (const_int 0))
5994                  (match_operand:SI 2 "register_operand" "")))
5995    (clobber (reg:CC 100))]
5996   ""
5997   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5998                                            (const_int 0)))
5999    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
6000                                (match_dup 2)))]
6001   "")
6002
6003 (define_split
6004   [(set (match_operand:SI 0 "register_operand" "")
6005         (minus:SI (match_operand:SI 2 "register_operand" "")
6006                   (eq:SI (match_operand:SI 1 "register_operand" "")
6007                          (const_int 0))))
6008    (clobber (reg:CC 100))]
6009   ""
6010   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
6011                                            (const_int 0)))
6012    (set (match_dup 0) (minus:SI (match_dup 2)
6013                                 (geu:SI (reg:CC 100) (const_int 0))))]
6014   "")
6015 \f
6016 ;; Peepholes go at the end.
6017
6018 ;; Optimize consecutive loads or stores into ldd and std when possible.
6019 ;; The conditions in which we do this are very restricted and are 
6020 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
6021
6022 (define_peephole
6023   [(set (match_operand:SI 0 "memory_operand" "")
6024       (const_int 0))
6025    (set (match_operand:SI 1 "memory_operand" "")
6026       (const_int 0))]
6027   "TARGET_V9
6028    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
6029    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[1], 0))"
6030   "stx %%g0,%0")
6031
6032 (define_peephole
6033   [(set (match_operand:SI 0 "memory_operand" "")
6034       (const_int 0))
6035    (set (match_operand:SI 1 "memory_operand" "")
6036       (const_int 0))]
6037   "TARGET_V9
6038    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
6039    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[0], 0))"
6040   "stx %%g0,%1")
6041
6042 (define_peephole
6043   [(set (match_operand:SI 0 "register_operand" "=rf")
6044         (match_operand:SI 1 "memory_operand" ""))
6045    (set (match_operand:SI 2 "register_operand" "=rf")
6046         (match_operand:SI 3 "memory_operand" ""))]
6047    "registers_ok_for_ldd_peep (operands[0], operands[2]) 
6048    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
6049    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 
6050   "ldd %1,%0")
6051
6052 (define_peephole
6053   [(set (match_operand:SI 0 "memory_operand" "")
6054         (match_operand:SI 1 "register_operand" "rf"))
6055    (set (match_operand:SI 2 "memory_operand" "")
6056         (match_operand:SI 3 "register_operand" "rf"))]
6057    "registers_ok_for_ldd_peep (operands[1], operands[3]) 
6058    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
6059    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
6060   "std %1,%0")
6061  
6062 (define_peephole
6063   [(set (match_operand:SF 0 "register_operand" "=fr")
6064         (match_operand:SF 1 "memory_operand" ""))
6065    (set (match_operand:SF 2 "register_operand" "=fr")
6066         (match_operand:SF 3 "memory_operand" ""))]
6067    "registers_ok_for_ldd_peep (operands[0], operands[2]) 
6068    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
6069    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
6070   "ldd %1,%0")
6071
6072 (define_peephole
6073   [(set (match_operand:SF 0 "memory_operand" "")
6074         (match_operand:SF 1 "register_operand" "fr"))
6075    (set (match_operand:SF 2 "memory_operand" "")
6076         (match_operand:SF 3 "register_operand" "fr"))]
6077    "registers_ok_for_ldd_peep (operands[1], operands[3]) 
6078    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
6079    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
6080   "std %1,%0")
6081
6082 (define_peephole
6083   [(set (match_operand:SI 0 "register_operand" "=rf")
6084         (match_operand:SI 1 "memory_operand" ""))
6085    (set (match_operand:SI 2 "register_operand" "=rf")
6086         (match_operand:SI 3 "memory_operand" ""))]
6087    "registers_ok_for_ldd_peep (operands[2], operands[0]) 
6088    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
6089    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
6090   "ldd %3,%2")
6091
6092 (define_peephole
6093   [(set (match_operand:SI 0 "memory_operand" "")
6094         (match_operand:SI 1 "register_operand" "rf"))
6095    (set (match_operand:SI 2 "memory_operand" "")
6096         (match_operand:SI 3 "register_operand" "rf"))]
6097    "registers_ok_for_ldd_peep (operands[3], operands[1]) 
6098    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
6099    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
6100   "std %3,%2")
6101  
6102 (define_peephole
6103   [(set (match_operand:SF 0 "register_operand" "=fr")
6104         (match_operand:SF 1 "memory_operand" ""))
6105    (set (match_operand:SF 2 "register_operand" "=fr")
6106         (match_operand:SF 3 "memory_operand" ""))]
6107    "registers_ok_for_ldd_peep (operands[2], operands[0]) 
6108    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
6109    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
6110   "ldd %3,%2")
6111
6112 (define_peephole
6113   [(set (match_operand:SF 0 "memory_operand" "")
6114         (match_operand:SF 1 "register_operand" "fr"))
6115    (set (match_operand:SF 2 "memory_operand" "")
6116         (match_operand:SF 3 "register_operand" "fr"))]
6117    "registers_ok_for_ldd_peep (operands[3], operands[1]) 
6118    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
6119    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
6120   "std %3,%2")
6121  
6122 ;; Optimize the case of following a reg-reg move with a test
6123 ;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
6124 ;; This can result from a float to fix conversion.
6125
6126 (define_peephole
6127   [(set (match_operand:SI 0 "register_operand" "=r")
6128         (match_operand:SI 1 "register_operand" "r"))
6129    (set (reg:CC 100)
6130         (compare:CC (match_operand:SI 2 "register_operand" "r")
6131                     (const_int 0)))]
6132   "(rtx_equal_p (operands[2], operands[0])
6133     || rtx_equal_p (operands[2], operands[1]))
6134    && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
6135   "orcc %1,0,%0")
6136
6137 (define_peephole
6138   [(set (match_operand:DI 0 "register_operand" "=r")
6139         (match_operand:DI 1 "register_operand" "r"))
6140    (set (reg:CCX 100)
6141         (compare:CCX (match_operand:DI 2 "register_operand" "r")
6142                     (const_int 0)))]
6143   "TARGET_ARCH64
6144    && (rtx_equal_p (operands[2], operands[0])
6145        || rtx_equal_p (operands[2], operands[1]))
6146    && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
6147   "orcc %1,0,%0")
6148
6149 ;; Do {sign,zero}-extended compares somewhat more efficiently.
6150 ;; ??? Is this now the Right Way to do this?  Or will SCRATCH
6151 ;;     eventually have some impact here?
6152
6153 (define_peephole
6154   [(set (match_operand:HI 0 "register_operand" "")
6155         (match_operand:HI 1 "memory_operand" ""))
6156    (set (match_operand:SI 2 "register_operand" "")
6157         (sign_extend:SI (match_dup 0)))
6158    (set (reg:CC 100)
6159         (compare:CC (match_dup 2)
6160                     (const_int 0)))]
6161   ""
6162   "ldsh %1,%0\;orcc %0,0,%2")
6163
6164 (define_peephole
6165   [(set (match_operand:HI 0 "register_operand" "")
6166         (match_operand:HI 1 "memory_operand" ""))
6167    (set (match_operand:DI 2 "register_operand" "")
6168         (sign_extend:DI (match_dup 0)))
6169    (set (reg:CCX 100)
6170         (compare:CCX (match_dup 2)
6171                      (const_int 0)))]
6172   "TARGET_ARCH64"
6173   "ldsh %1,%0\;orcc %0,0,%2")
6174
6175 (define_peephole
6176   [(set (match_operand:QI 0 "register_operand" "")
6177         (match_operand:QI 1 "memory_operand" ""))
6178    (set (match_operand:SI 2 "register_operand" "")
6179         (sign_extend:SI (match_dup 0)))
6180    (set (reg:CC 100)
6181         (compare:CC (match_dup 2)
6182                     (const_int 0)))]
6183   ""
6184   "ldsb %1,%0\;orcc %0,0,%2")
6185
6186 (define_peephole
6187   [(set (match_operand:QI 0 "register_operand" "")
6188         (match_operand:QI 1 "memory_operand" ""))
6189    (set (match_operand:DI 2 "register_operand" "")
6190         (sign_extend:DI (match_dup 0)))
6191    (set (reg:CCX 100)
6192         (compare:CCX (match_dup 2)
6193                      (const_int 0)))]
6194   "TARGET_ARCH64"
6195   "ldsb %1,%0\;orcc %0,0,%2")
6196
6197 ;; Floating-point move peepholes
6198 ;; ??? v9: Do we want similar ones?
6199
6200 (define_peephole
6201   [(set (match_operand:SI 0 "register_operand" "=r")
6202         (lo_sum:SI (match_dup 0)
6203                    (match_operand:SI 1 "immediate_operand" "i")))
6204    (set (match_operand:DF 2 "register_operand" "=er")
6205         (mem:DF (match_dup 0)))]
6206   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
6207   "*
6208 {
6209   /* Go by way of output_move_double in case the register in operand 2
6210      is not properly aligned for ldd.  */
6211   operands[1] = gen_rtx (MEM, DFmode,
6212                          gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
6213   operands[0] = operands[2];
6214   return output_move_double (operands);
6215 }")
6216
6217 (define_peephole
6218   [(set (match_operand:SI 0 "register_operand" "=r")
6219         (lo_sum:SI (match_dup 0)
6220                    (match_operand:SI 1 "immediate_operand" "i")))
6221    (set (match_operand:SF 2 "register_operand" "=fr")
6222         (mem:SF (match_dup 0)))]
6223   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
6224   "ld [%0+%%lo(%a1)],%2")
6225
6226 ;; Return peepholes.  First the "normal" ones.
6227 ;; These are necessary to catch insns ending up in the epilogue delay list.
6228
6229 (define_insn "*return_qi"
6230   [(set (match_operand:QI 0 "restore_operand" "")
6231         (match_operand:QI 1 "arith_operand" "rI"))
6232    (return)]
6233   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
6234   "*
6235 {
6236   if (! TARGET_ARCH64 && current_function_returns_struct)
6237     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
6238   else
6239     return \"ret\;restore %%g0,%1,%Y0\";
6240 }"
6241   [(set_attr "type" "multi")])
6242
6243 (define_insn "*return_hi"
6244   [(set (match_operand:HI 0 "restore_operand" "")
6245         (match_operand:HI 1 "arith_operand" "rI"))
6246    (return)]
6247   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
6248   "*
6249 {
6250   if (! TARGET_ARCH64 && current_function_returns_struct)
6251     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
6252   else
6253     return \"ret\;restore %%g0,%1,%Y0\";
6254 }"
6255   [(set_attr "type" "multi")])
6256
6257 (define_insn "*return_si"
6258   [(set (match_operand:SI 0 "restore_operand" "")
6259         (match_operand:SI 1 "arith_operand" "rI"))
6260    (return)]
6261   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
6262   "*
6263 {
6264   if (! TARGET_ARCH64 && current_function_returns_struct)
6265     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
6266   else
6267     return \"ret\;restore %%g0,%1,%Y0\";
6268 }"
6269   [(set_attr "type" "multi")])
6270
6271 ;; The following pattern is only generated by delayed-branch scheduling,
6272 ;; when the insn winds up in the epilogue.  This can only happen when
6273 ;; ! TARGET_FPU because otherwise fp return values are in %f0.
6274 (define_insn "*return_sf_no_fpu"
6275   [(set (match_operand:SF 0 "restore_operand" "r")
6276         (match_operand:SF 1 "register_operand" "r"))
6277    (return)]
6278   "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
6279   "*
6280 {
6281   if (! TARGET_ARCH64 && current_function_returns_struct)
6282     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
6283   else
6284     return \"ret\;restore %%g0,%1,%Y0\";
6285 }"
6286   [(set_attr "type" "multi")])
6287
6288 (define_insn "*return_addsi"
6289   [(set (match_operand:SI 0 "restore_operand" "")
6290         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
6291                  (match_operand:SI 2 "arith_operand" "rI")))
6292    (return)]
6293   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0
6294    && (register_operand (operands[1], SImode)
6295        || register_operand (operands[2], SImode))"
6296   "*
6297 {
6298   if (! TARGET_ARCH64 && current_function_returns_struct)
6299     return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
6300   else
6301     return \"ret\;restore %r1,%2,%Y0\";
6302 }"
6303   [(set_attr "type" "multi")])
6304
6305 (define_insn "*return_di"
6306   [(set (match_operand:DI 0 "restore_operand" "")
6307         (match_operand:DI 1 "arith_double_operand" "rHI"))
6308    (return)]
6309   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
6310   "ret\;restore %%g0,%1,%Y0"
6311   [(set_attr "type" "multi")])
6312
6313 (define_insn "*return_adddi"
6314   [(set (match_operand:DI 0 "restore_operand" "")
6315         (plus:DI (match_operand:DI 1 "arith_operand" "%r")
6316                  (match_operand:DI 2 "arith_double_operand" "rHI")))
6317    (return)]
6318   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
6319   "ret\;restore %r1,%2,%Y0"
6320   [(set_attr "type" "multi")])
6321
6322 ;; The following pattern is only generated by delayed-branch scheduling,
6323 ;; when the insn winds up in the epilogue.
6324 (define_insn "*return_sf"
6325   [(set (reg:SF 32)
6326         (match_operand:SF 0 "register_operand" "f"))
6327    (return)]
6328   "! TARGET_EPILOGUE"
6329   "ret\;fmovs %0,%%f0"
6330   [(set_attr "type" "multi")])
6331
6332 ;; Now peepholes to do a call followed by a jump.
6333
6334 (define_peephole
6335   [(parallel [(set (match_operand 0 "" "")
6336                    (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
6337                          (match_operand 2 "" "")))
6338               (clobber (reg:SI 15))])
6339    (set (pc) (label_ref (match_operand 3 "" "")))]
6340   "short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
6341   "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
6342
6343 (define_peephole
6344   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
6345                     (match_operand 1 "" ""))
6346               (clobber (reg:SI 15))])
6347    (set (pc) (label_ref (match_operand 2 "" "")))]
6348   "short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
6349   "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
6350
6351 (define_peephole
6352   [(parallel [(set (match_operand 0 "" "")
6353                    (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
6354                          (match_operand 2 "" "")))
6355               (clobber (reg:DI 15))])
6356    (set (pc) (label_ref (match_operand 3 "" "")))]
6357   "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
6358   "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
6359
6360 (define_peephole
6361   [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
6362                     (match_operand 1 "" ""))
6363               (clobber (reg:DI 15))])
6364    (set (pc) (label_ref (match_operand 2 "" "")))]
6365   "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
6366   "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
6367
6368 ;; Other miscellaneous peepholes.
6369
6370 ;; (reg:SI 100) is created by the {add,neg,sub}di patterns.
6371 (define_peephole
6372   [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
6373                    (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
6374                              (reg:SI 100)))
6375               (clobber (reg:CC 100))])
6376    (set (reg:CC 100) (compare (match_dup 0) (const_int 0)))]
6377   ""
6378   "subxcc %r1,0,%0")
6379
6380 ;; After a nonlocal goto, we need to restore the PIC register, but only
6381 ;; if we need it.  So do nothing much here, but we'll check for this in
6382 ;; finalize_pic.
6383
6384 (define_insn "nonlocal_goto_receiver"
6385   [(unspec_volatile [(const_int 0)] 4)]
6386   "flag_pic"
6387   "")