OSDN Git Service

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