OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.md
1 ;; Machine description for SPARC chip for GCC
2 ;;  Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 ;;  1999, 2000, 2001, 2002, 2003, 2004, 2005,2006 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 GCC.
9
10 ;; GCC 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 ;; GCC 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 GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, 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_LOAD_PCREL_SYM       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    (UNSPEC_TLSGD                30)
43    (UNSPEC_TLSLDM               31)
44    (UNSPEC_TLSLDO               32)
45    (UNSPEC_TLSIE                33)
46    (UNSPEC_TLSLE                34)
47    (UNSPEC_TLSLD_BASE           35)
48
49    (UNSPEC_FPACK16              40)
50    (UNSPEC_FPACK32              41)
51    (UNSPEC_FPACKFIX             42)
52    (UNSPEC_FEXPAND              43)
53    (UNSPEC_FPMERGE              44)
54    (UNSPEC_MUL16AL              45)
55    (UNSPEC_MUL8UL               46)
56    (UNSPEC_MULDUL               47)
57    (UNSPEC_ALIGNDATA            48)
58    (UNSPEC_ALIGNADDR            49)
59    (UNSPEC_PDIST                50)
60
61    (UNSPEC_SP_SET               60)
62    (UNSPEC_SP_TEST              61)
63   ])
64
65 (define_constants
66   [(UNSPECV_BLOCKAGE            0)
67    (UNSPECV_FLUSHW              1)
68    (UNSPECV_GOTO                2)
69    (UNSPECV_FLUSH               4)
70    (UNSPECV_SETJMP              5)
71    (UNSPECV_SAVEW               6)
72    (UNSPECV_MEMBAR              7)
73    (UNSPECV_CAS                 8)
74    (UNSPECV_SWAP                9)
75    (UNSPECV_LDSTUB              10)
76   ])
77
78 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
79 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
80 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
81 ;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
82 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
83
84
85 ;; Attribute for cpu type.
86 ;; These must match the values for enum processor_type in sparc.h.
87 (define_attr "cpu"
88   "v7,
89    cypress,
90    v8,
91    supersparc,
92    sparclite,f930,f934,
93    hypersparc,sparclite86x,
94    sparclet,tsc701,
95    v9,
96    ultrasparc,
97    ultrasparc3,
98    niagara"
99   (const (symbol_ref "sparc_cpu_attr")))
100
101 ;; Attribute for the instruction set.
102 ;; At present we only need to distinguish v9/!v9, but for clarity we
103 ;; test TARGET_V8 too.
104 (define_attr "isa" "v7,v8,v9,sparclet"
105  (const
106   (cond [(symbol_ref "TARGET_V9") (const_string "v9")
107          (symbol_ref "TARGET_V8") (const_string "v8")
108          (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
109         (const_string "v7"))))
110
111 ;; Insn type.
112 (define_attr "type"
113   "ialu,compare,shift,
114    load,sload,store,
115    uncond_branch,branch,call,sibcall,call_no_delay_slot,return,
116    imul,idiv,
117    fpload,fpstore,
118    fp,fpmove,
119    fpcmove,fpcrmove,
120    fpcmp,
121    fpmul,fpdivs,fpdivd,
122    fpsqrts,fpsqrtd,
123    fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp,
124    cmove,
125    ialuX,
126    multi,savew,flushw,iflush,trap"
127   (const_string "ialu"))
128
129 ;; True if branch/call has empty delay slot and will emit a nop in it
130 (define_attr "empty_delay_slot" "false,true"
131   (symbol_ref "empty_delay_slot (insn)"))
132
133 (define_attr "branch_type" "none,icc,fcc,reg"
134   (const_string "none"))
135
136 (define_attr "pic" "false,true"
137   (symbol_ref "flag_pic != 0"))
138
139 (define_attr "calls_alloca" "false,true"
140   (symbol_ref "current_function_calls_alloca != 0"))
141
142 (define_attr "calls_eh_return" "false,true"
143    (symbol_ref "current_function_calls_eh_return !=0 "))
144    
145 (define_attr "leaf_function" "false,true"
146   (symbol_ref "current_function_uses_only_leaf_regs != 0"))
147
148 (define_attr "delayed_branch" "false,true"
149   (symbol_ref "flag_delayed_branch != 0"))
150
151 ;; Length (in # of insns).
152 ;; Beware that setting a length greater or equal to 3 for conditional branches
153 ;; has a side-effect (see output_cbranch and output_v9branch).
154 (define_attr "length" ""
155   (cond [(eq_attr "type" "uncond_branch,call")
156            (if_then_else (eq_attr "empty_delay_slot" "true")
157              (const_int 2)
158              (const_int 1))
159          (eq_attr "type" "sibcall")
160            (if_then_else (eq_attr "leaf_function" "true")
161              (if_then_else (eq_attr "empty_delay_slot" "true")
162                (const_int 3)
163                (const_int 2))
164              (if_then_else (eq_attr "empty_delay_slot" "true")
165                (const_int 2)
166                (const_int 1)))
167          (eq_attr "branch_type" "icc")
168            (if_then_else (match_operand 0 "noov_compare64_operator" "")
169              (if_then_else (lt (pc) (match_dup 1))
170                (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
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 1)) (const_int 260000))
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              (if_then_else (eq_attr "empty_delay_slot" "true")
185                (const_int 2)
186                (const_int 1)))
187          (eq_attr "branch_type" "fcc")
188            (if_then_else (match_operand 0 "fcc0_register_operand" "")
189              (if_then_else (eq_attr "empty_delay_slot" "true")
190                (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0))
191                  (const_int 3)
192                  (const_int 2))
193                (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0))
194                  (const_int 2)
195                  (const_int 1)))
196              (if_then_else (lt (pc) (match_dup 2))
197                (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
198                  (if_then_else (eq_attr "empty_delay_slot" "true")
199                    (const_int 2)
200                    (const_int 1))
201                  (if_then_else (eq_attr "empty_delay_slot" "true")
202                    (const_int 4)
203                    (const_int 3)))
204                (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
205                  (if_then_else (eq_attr "empty_delay_slot" "true")
206                    (const_int 2)
207                    (const_int 1))
208                  (if_then_else (eq_attr "empty_delay_slot" "true")
209                    (const_int 4)
210                    (const_int 3)))))
211          (eq_attr "branch_type" "reg")
212            (if_then_else (lt (pc) (match_dup 2))
213              (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
214                (if_then_else (eq_attr "empty_delay_slot" "true")
215                  (const_int 2)
216                  (const_int 1))
217                (if_then_else (eq_attr "empty_delay_slot" "true")
218                  (const_int 4)
219                  (const_int 3)))
220              (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
221                (if_then_else (eq_attr "empty_delay_slot" "true")
222                  (const_int 2)
223                  (const_int 1))
224                (if_then_else (eq_attr "empty_delay_slot" "true")
225                  (const_int 4)
226                  (const_int 3))))
227          ] (const_int 1)))
228
229 ;; FP precision.
230 (define_attr "fptype" "single,double"
231   (const_string "single"))
232
233 ;; UltraSPARC-III integer load type.
234 (define_attr "us3load_type" "2cycle,3cycle"
235   (const_string "2cycle"))
236
237 (define_asm_attributes
238   [(set_attr "length" "2")
239    (set_attr "type" "multi")])
240
241 ;; Attributes for instruction and branch scheduling
242 (define_attr "tls_call_delay" "false,true"
243   (symbol_ref "tls_call_delay (insn)"))
244
245 (define_attr "in_call_delay" "false,true"
246   (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
247                 (const_string "false")
248          (eq_attr "type" "load,fpload,store,fpstore")
249                 (if_then_else (eq_attr "length" "1")
250                               (const_string "true")
251                               (const_string "false"))]
252         (if_then_else (and (eq_attr "length" "1")
253                            (eq_attr "tls_call_delay" "true"))
254                       (const_string "true")
255                       (const_string "false"))))
256
257 (define_attr "eligible_for_sibcall_delay" "false,true"
258   (symbol_ref "eligible_for_sibcall_delay (insn)"))
259
260 (define_attr "eligible_for_return_delay" "false,true"
261   (symbol_ref "eligible_for_return_delay (insn)"))
262
263 ;; ??? !v9: Should implement the notion of predelay slots for floating-point
264 ;; branches.  This would allow us to remove the nop always inserted before
265 ;; a floating point branch.
266
267 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
268 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
269 ;; This is because doing so will add several pipeline stalls to the path
270 ;; that the load/store did not come from.  Unfortunately, there is no way
271 ;; to prevent fill_eager_delay_slots from using load/store without completely
272 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
273 ;; because it prevents us from moving back the final store of inner loops.
274
275 (define_attr "in_branch_delay" "false,true"
276   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
277                      (eq_attr "length" "1"))
278                 (const_string "true")
279                 (const_string "false")))
280
281 (define_attr "in_uncond_branch_delay" "false,true"
282   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
283                      (eq_attr "length" "1"))
284                 (const_string "true")
285                 (const_string "false")))
286
287 (define_attr "in_annul_branch_delay" "false,true"
288   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
289                      (eq_attr "length" "1"))
290                 (const_string "true")
291                 (const_string "false")))
292
293 (define_delay (eq_attr "type" "call")
294   [(eq_attr "in_call_delay" "true") (nil) (nil)])
295
296 (define_delay (eq_attr "type" "sibcall")
297   [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
298
299 (define_delay (eq_attr "type" "branch")
300   [(eq_attr "in_branch_delay" "true")
301    (nil) (eq_attr "in_annul_branch_delay" "true")])
302
303 (define_delay (eq_attr "type" "uncond_branch")
304   [(eq_attr "in_uncond_branch_delay" "true")
305    (nil) (nil)])
306
307 (define_delay (eq_attr "type" "return")
308   [(eq_attr "eligible_for_return_delay" "true") (nil) (nil)])
309
310
311 ;; Include SPARC DFA schedulers
312
313 (include "cypress.md")
314 (include "supersparc.md")
315 (include "hypersparc.md")
316 (include "sparclet.md")
317 (include "ultra1_2.md")
318 (include "ultra3.md")
319 (include "niagara.md")
320
321
322 ;; Operand and operator predicates.
323
324 (include "predicates.md")
325
326
327 ;; Compare instructions.
328
329 ;; We generate RTL for comparisons and branches by having the cmpxx 
330 ;; patterns store away the operands.  Then, the scc and bcc patterns
331 ;; emit RTL for both the compare and the branch.
332 ;;
333 ;; We do this because we want to generate different code for an sne and
334 ;; seq insn.  In those cases, if the second operand of the compare is not
335 ;; const0_rtx, we want to compute the xor of the two operands and test
336 ;; it against zero.
337 ;;
338 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
339 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
340 ;; insns that actually require more than one machine instruction.
341
342 (define_expand "cmpsi"
343   [(set (reg:CC 100)
344         (compare:CC (match_operand:SI 0 "compare_operand" "")
345                     (match_operand:SI 1 "arith_operand" "")))]
346   ""
347 {
348   if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
349     operands[0] = force_reg (SImode, operands[0]);
350
351   sparc_compare_op0 = operands[0];
352   sparc_compare_op1 = operands[1];
353   DONE;
354 })
355
356 (define_expand "cmpdi"
357   [(set (reg:CCX 100)
358         (compare:CCX (match_operand:DI 0 "compare_operand" "")
359                      (match_operand:DI 1 "arith_operand" "")))]
360   "TARGET_ARCH64"
361 {
362   if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
363     operands[0] = force_reg (DImode, operands[0]);
364
365   sparc_compare_op0 = operands[0];
366   sparc_compare_op1 = operands[1];
367   DONE;
368 })
369
370 (define_expand "cmpsf"
371   ;; The 96 here isn't ever used by anyone.
372   [(set (reg:CCFP 96)
373         (compare:CCFP (match_operand:SF 0 "register_operand" "")
374                       (match_operand:SF 1 "register_operand" "")))]
375   "TARGET_FPU"
376 {
377   sparc_compare_op0 = operands[0];
378   sparc_compare_op1 = operands[1];
379   DONE;
380 })
381
382 (define_expand "cmpdf"
383   ;; The 96 here isn't ever used by anyone.
384   [(set (reg:CCFP 96)
385         (compare:CCFP (match_operand:DF 0 "register_operand" "")
386                       (match_operand:DF 1 "register_operand" "")))]
387   "TARGET_FPU"
388 {
389   sparc_compare_op0 = operands[0];
390   sparc_compare_op1 = operands[1];
391   DONE;
392 })
393
394 (define_expand "cmptf"
395   ;; The 96 here isn't ever used by anyone.
396   [(set (reg:CCFP 96)
397         (compare:CCFP (match_operand:TF 0 "register_operand" "")
398                       (match_operand:TF 1 "register_operand" "")))]
399   "TARGET_FPU"
400 {
401   sparc_compare_op0 = operands[0];
402   sparc_compare_op1 = operands[1];
403   DONE;
404 })
405
406 ;; Now the compare DEFINE_INSNs.
407
408 (define_insn "*cmpsi_insn"
409   [(set (reg:CC 100)
410         (compare:CC (match_operand:SI 0 "register_operand" "r")
411                     (match_operand:SI 1 "arith_operand" "rI")))]
412   ""
413   "cmp\t%0, %1"
414   [(set_attr "type" "compare")])
415
416 (define_insn "*cmpdi_sp64"
417   [(set (reg:CCX 100)
418         (compare:CCX (match_operand:DI 0 "register_operand" "r")
419                      (match_operand:DI 1 "arith_operand" "rI")))]
420   "TARGET_ARCH64"
421   "cmp\t%0, %1"
422   [(set_attr "type" "compare")])
423
424 (define_insn "*cmpsf_fpe"
425   [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
426         (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
427                        (match_operand:SF 2 "register_operand" "f")))]
428   "TARGET_FPU"
429 {
430   if (TARGET_V9)
431     return "fcmpes\t%0, %1, %2";
432   return "fcmpes\t%1, %2";
433 }
434   [(set_attr "type" "fpcmp")])
435
436 (define_insn "*cmpdf_fpe"
437   [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
438         (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
439                        (match_operand:DF 2 "register_operand" "e")))]
440   "TARGET_FPU"
441 {
442   if (TARGET_V9)
443     return "fcmped\t%0, %1, %2";
444   return "fcmped\t%1, %2";
445 }
446   [(set_attr "type" "fpcmp")
447    (set_attr "fptype" "double")])
448
449 (define_insn "*cmptf_fpe"
450   [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
451         (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
452                        (match_operand:TF 2 "register_operand" "e")))]
453   "TARGET_FPU && TARGET_HARD_QUAD"
454 {
455   if (TARGET_V9)
456     return "fcmpeq\t%0, %1, %2";
457   return "fcmpeq\t%1, %2";
458 }
459   [(set_attr "type" "fpcmp")])
460
461 (define_insn "*cmpsf_fp"
462   [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
463         (compare:CCFP (match_operand:SF 1 "register_operand" "f")
464                       (match_operand:SF 2 "register_operand" "f")))]
465   "TARGET_FPU"
466 {
467   if (TARGET_V9)
468     return "fcmps\t%0, %1, %2";
469   return "fcmps\t%1, %2";
470 }
471   [(set_attr "type" "fpcmp")])
472
473 (define_insn "*cmpdf_fp"
474   [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
475         (compare:CCFP (match_operand:DF 1 "register_operand" "e")
476                       (match_operand:DF 2 "register_operand" "e")))]
477   "TARGET_FPU"
478 {
479   if (TARGET_V9)
480     return "fcmpd\t%0, %1, %2";
481   return "fcmpd\t%1, %2";
482 }
483   [(set_attr "type" "fpcmp")
484    (set_attr "fptype" "double")])
485
486 (define_insn "*cmptf_fp"
487   [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
488         (compare:CCFP (match_operand:TF 1 "register_operand" "e")
489                       (match_operand:TF 2 "register_operand" "e")))]
490   "TARGET_FPU && TARGET_HARD_QUAD"
491 {
492   if (TARGET_V9)
493     return "fcmpq\t%0, %1, %2";
494   return "fcmpq\t%1, %2";
495 }
496   [(set_attr "type" "fpcmp")])
497 \f
498 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
499 ;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
500 ;; the same code as v8 (the addx/subx method has more applications).  The
501 ;; exception to this is "reg != 0" which can be done in one instruction on v9
502 ;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
503 ;; branches.
504
505 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
506 ;; generate addcc/subcc instructions.
507
508 (define_expand "seqsi_special"
509   [(set (match_dup 3)
510         (xor:SI (match_operand:SI 1 "register_operand" "")
511                 (match_operand:SI 2 "register_operand" "")))
512    (parallel [(set (match_operand:SI 0 "register_operand" "")
513                    (eq:SI (match_dup 3) (const_int 0)))
514               (clobber (reg:CC 100))])]
515   ""
516   { operands[3] = gen_reg_rtx (SImode); })
517
518 (define_expand "seqdi_special"
519   [(set (match_dup 3)
520         (xor:DI (match_operand:DI 1 "register_operand" "")
521                 (match_operand:DI 2 "register_operand" "")))
522    (set (match_operand:DI 0 "register_operand" "")
523         (eq:DI (match_dup 3) (const_int 0)))]
524   "TARGET_ARCH64"
525   { operands[3] = gen_reg_rtx (DImode); })
526
527 (define_expand "snesi_special"
528   [(set (match_dup 3)
529         (xor:SI (match_operand:SI 1 "register_operand" "")
530                 (match_operand:SI 2 "register_operand" "")))
531    (parallel [(set (match_operand:SI 0 "register_operand" "")
532                    (ne:SI (match_dup 3) (const_int 0)))
533               (clobber (reg:CC 100))])]
534   ""
535   { operands[3] = gen_reg_rtx (SImode); })
536
537 (define_expand "snedi_special"
538   [(set (match_dup 3)
539         (xor:DI (match_operand:DI 1 "register_operand" "")
540                 (match_operand:DI 2 "register_operand" "")))
541    (set (match_operand:DI 0 "register_operand" "")
542         (ne:DI (match_dup 3) (const_int 0)))]
543   "TARGET_ARCH64"
544   { operands[3] = gen_reg_rtx (DImode); })
545
546 (define_expand "seqdi_special_trunc"
547   [(set (match_dup 3)
548         (xor:DI (match_operand:DI 1 "register_operand" "")
549                 (match_operand:DI 2 "register_operand" "")))
550    (set (match_operand:SI 0 "register_operand" "")
551         (eq:SI (match_dup 3) (const_int 0)))]
552   "TARGET_ARCH64"
553   { operands[3] = gen_reg_rtx (DImode); })
554
555 (define_expand "snedi_special_trunc"
556   [(set (match_dup 3)
557         (xor:DI (match_operand:DI 1 "register_operand" "")
558                 (match_operand:DI 2 "register_operand" "")))
559    (set (match_operand:SI 0 "register_operand" "")
560         (ne:SI (match_dup 3) (const_int 0)))]
561   "TARGET_ARCH64"
562   { operands[3] = gen_reg_rtx (DImode); })
563
564 (define_expand "seqsi_special_extend"
565   [(set (match_dup 3)
566         (xor:SI (match_operand:SI 1 "register_operand" "")
567                 (match_operand:SI 2 "register_operand" "")))
568    (parallel [(set (match_operand:DI 0 "register_operand" "")
569                    (eq:DI (match_dup 3) (const_int 0)))
570               (clobber (reg:CC 100))])]
571   "TARGET_ARCH64"
572   { operands[3] = gen_reg_rtx (SImode); })
573
574 (define_expand "snesi_special_extend"
575   [(set (match_dup 3)
576         (xor:SI (match_operand:SI 1 "register_operand" "")
577                 (match_operand:SI 2 "register_operand" "")))
578    (parallel [(set (match_operand:DI 0 "register_operand" "")
579                    (ne:DI (match_dup 3) (const_int 0)))
580               (clobber (reg:CC 100))])]
581   "TARGET_ARCH64"
582   { operands[3] = gen_reg_rtx (SImode); })
583
584 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
585 ;; However, the code handles both SImode and DImode.
586 (define_expand "seq"
587   [(set (match_operand:SI 0 "int_register_operand" "")
588         (eq:SI (match_dup 1) (const_int 0)))]
589   ""
590 {
591   if (GET_MODE (sparc_compare_op0) == SImode)
592     {
593       rtx pat;
594
595       if (GET_MODE (operands[0]) == SImode)
596         pat = gen_seqsi_special (operands[0], sparc_compare_op0,
597                                  sparc_compare_op1);
598       else if (! TARGET_ARCH64)
599         FAIL;
600       else
601         pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
602                                         sparc_compare_op1);
603       emit_insn (pat);
604       DONE;
605     }
606   else if (GET_MODE (sparc_compare_op0) == DImode)
607     {
608       rtx pat;
609
610       if (! TARGET_ARCH64)
611         FAIL;
612       else if (GET_MODE (operands[0]) == SImode)
613         pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
614                                        sparc_compare_op1);
615       else
616         pat = gen_seqdi_special (operands[0], sparc_compare_op0,
617                                  sparc_compare_op1);
618       emit_insn (pat);
619       DONE;
620     }
621   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
622     {
623       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
624       emit_jump_insn (gen_sne (operands[0]));
625       DONE;
626     }
627   else if (TARGET_V9)
628     {
629       if (gen_v9_scc (EQ, operands))
630         DONE;
631       /* fall through */
632     }
633   FAIL;
634 })
635
636 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
637 ;; However, the code handles both SImode and DImode.
638 (define_expand "sne"
639   [(set (match_operand:SI 0 "int_register_operand" "")
640         (ne:SI (match_dup 1) (const_int 0)))]
641   ""
642 {
643   if (GET_MODE (sparc_compare_op0) == SImode)
644     {
645       rtx pat;
646
647       if (GET_MODE (operands[0]) == SImode)
648         pat = gen_snesi_special (operands[0], sparc_compare_op0,
649                                  sparc_compare_op1);
650       else if (! TARGET_ARCH64)
651         FAIL;
652       else
653         pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
654                                         sparc_compare_op1);
655       emit_insn (pat);
656       DONE;
657     }
658   else if (GET_MODE (sparc_compare_op0) == DImode)
659     {
660       rtx pat;
661
662       if (! TARGET_ARCH64)
663         FAIL;
664       else if (GET_MODE (operands[0]) == SImode)
665         pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
666                                        sparc_compare_op1);
667       else
668         pat = gen_snedi_special (operands[0], sparc_compare_op0,
669                                  sparc_compare_op1);
670       emit_insn (pat);
671       DONE;
672     }
673   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
674     {
675       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
676       emit_jump_insn (gen_sne (operands[0]));
677       DONE;
678     }
679   else if (TARGET_V9)
680     {
681       if (gen_v9_scc (NE, operands))
682         DONE;
683       /* fall through */
684     }
685   FAIL;
686 })
687
688 (define_expand "sgt"
689   [(set (match_operand:SI 0 "int_register_operand" "")
690         (gt:SI (match_dup 1) (const_int 0)))]
691   ""
692 {
693   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
694     {
695       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
696       emit_jump_insn (gen_sne (operands[0]));
697       DONE;
698     }
699   else if (TARGET_V9)
700     {
701       if (gen_v9_scc (GT, operands))
702         DONE;
703       /* fall through */
704     }
705   FAIL;
706 })
707
708 (define_expand "slt"
709   [(set (match_operand:SI 0 "int_register_operand" "")
710         (lt:SI (match_dup 1) (const_int 0)))]
711   ""
712 {
713   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
714     {
715       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
716       emit_jump_insn (gen_sne (operands[0]));
717       DONE;
718     }
719   else if (TARGET_V9)
720     {
721       if (gen_v9_scc (LT, operands))
722         DONE;
723       /* fall through */
724     }
725   FAIL;
726 })
727
728 (define_expand "sge"
729   [(set (match_operand:SI 0 "int_register_operand" "")
730         (ge:SI (match_dup 1) (const_int 0)))]
731   ""
732 {
733   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
734     {
735       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
736       emit_jump_insn (gen_sne (operands[0]));
737       DONE;
738     }
739   else if (TARGET_V9)
740     {
741       if (gen_v9_scc (GE, operands))
742         DONE;
743       /* fall through */
744     }
745   FAIL;
746 })
747
748 (define_expand "sle"
749   [(set (match_operand:SI 0 "int_register_operand" "")
750         (le:SI (match_dup 1) (const_int 0)))]
751   ""
752 {
753   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
754     {
755       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
756       emit_jump_insn (gen_sne (operands[0]));
757       DONE;
758     }
759   else if (TARGET_V9)
760     {
761       if (gen_v9_scc (LE, operands))
762         DONE;
763       /* fall through */
764     }
765   FAIL;
766 })
767
768 (define_expand "sgtu"
769   [(set (match_operand:SI 0 "int_register_operand" "")
770         (gtu:SI (match_dup 1) (const_int 0)))]
771   ""
772 {
773   if (! TARGET_V9)
774     {
775       rtx tem, pat;
776
777       /* We can do ltu easily, so if both operands are registers, swap them and
778          do a LTU.  */
779       if ((GET_CODE (sparc_compare_op0) == REG
780            || GET_CODE (sparc_compare_op0) == SUBREG)
781           && (GET_CODE (sparc_compare_op1) == REG
782               || GET_CODE (sparc_compare_op1) == SUBREG))
783         {
784           tem = sparc_compare_op0;
785           sparc_compare_op0 = sparc_compare_op1;
786           sparc_compare_op1 = tem;
787           pat = gen_sltu (operands[0]);
788           if (pat == NULL_RTX)
789             FAIL;
790           emit_insn (pat);
791           DONE;
792         }
793     }
794   else
795     {
796       if (gen_v9_scc (GTU, operands))
797         DONE;
798     }
799   FAIL;
800 })
801
802 (define_expand "sltu"
803   [(set (match_operand:SI 0 "int_register_operand" "")
804         (ltu:SI (match_dup 1) (const_int 0)))]
805   ""
806 {
807   if (TARGET_V9)
808     {
809       if (gen_v9_scc (LTU, operands))
810         DONE;
811     }
812   operands[1] = gen_compare_reg (LTU);
813 })
814
815 (define_expand "sgeu"
816   [(set (match_operand:SI 0 "int_register_operand" "")
817         (geu:SI (match_dup 1) (const_int 0)))]
818   ""
819 {
820   if (TARGET_V9)
821     {
822       if (gen_v9_scc (GEU, operands))
823         DONE;
824     }
825   operands[1] = gen_compare_reg (GEU);
826 })
827
828 (define_expand "sleu"
829   [(set (match_operand:SI 0 "int_register_operand" "")
830         (leu:SI (match_dup 1) (const_int 0)))]
831   ""
832 {
833   if (! TARGET_V9)
834     {
835       rtx tem, pat;
836
837       /* We can do geu easily, so if both operands are registers, swap them and
838          do a GEU.  */
839       if ((GET_CODE (sparc_compare_op0) == REG
840            || GET_CODE (sparc_compare_op0) == SUBREG)
841           && (GET_CODE (sparc_compare_op1) == REG
842               || GET_CODE (sparc_compare_op1) == SUBREG))
843         {
844           tem = sparc_compare_op0;
845           sparc_compare_op0 = sparc_compare_op1;
846           sparc_compare_op1 = tem;
847           pat = gen_sgeu (operands[0]);
848           if (pat == NULL_RTX)
849             FAIL;
850           emit_insn (pat);
851           DONE;
852         }
853     }
854   else
855     {
856       if (gen_v9_scc (LEU, operands))
857         DONE;
858     }
859   FAIL;
860 })
861
862 ;; Now the DEFINE_INSNs for the scc cases.
863
864 ;; The SEQ and SNE patterns are special because they can be done
865 ;; without any branching and do not involve a COMPARE.  We want
866 ;; them to always use the splits below so the results can be
867 ;; scheduled.
868
869 (define_insn_and_split "*snesi_zero"
870   [(set (match_operand:SI 0 "register_operand" "=r")
871         (ne:SI (match_operand:SI 1 "register_operand" "r")
872                (const_int 0)))
873    (clobber (reg:CC 100))]
874   ""
875   "#"
876   ""
877   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
878                                            (const_int 0)))
879    (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
880   ""
881   [(set_attr "length" "2")])
882
883 (define_insn_and_split "*neg_snesi_zero"
884   [(set (match_operand:SI 0 "register_operand" "=r")
885         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
886                        (const_int 0))))
887    (clobber (reg:CC 100))]
888   ""
889   "#"
890   ""
891   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
892                                            (const_int 0)))
893    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
894   ""
895   [(set_attr "length" "2")])
896
897 (define_insn_and_split "*snesi_zero_extend"
898   [(set (match_operand:DI 0 "register_operand" "=r")
899         (ne:DI (match_operand:SI 1 "register_operand" "r")
900                (const_int 0)))
901    (clobber (reg:CC 100))]
902   "TARGET_ARCH64"
903   "#"
904   "&& 1"
905   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
906                                                      (match_dup 1))
907                                            (const_int 0)))
908    (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
909                                                         (const_int 0))
910                                                (ltu:SI (reg:CC_NOOV 100)
911                                                        (const_int 0)))))]
912   ""
913   [(set_attr "length" "2")])
914
915 (define_insn_and_split "*snedi_zero"
916   [(set (match_operand:DI 0 "register_operand" "=&r")
917         (ne:DI (match_operand:DI 1 "register_operand" "r")
918                (const_int 0)))]
919   "TARGET_ARCH64"
920   "#"
921   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
922   [(set (match_dup 0) (const_int 0))
923    (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
924                                               (const_int 0))
925                                        (const_int 1)
926                                        (match_dup 0)))]
927   ""
928   [(set_attr "length" "2")])
929
930 (define_insn_and_split "*neg_snedi_zero"
931   [(set (match_operand:DI 0 "register_operand" "=&r")
932         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
933                        (const_int 0))))]
934   "TARGET_ARCH64"
935   "#"
936   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
937   [(set (match_dup 0) (const_int 0))
938    (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
939                                               (const_int 0))
940                                        (const_int -1)
941                                        (match_dup 0)))]
942   ""
943   [(set_attr "length" "2")])
944
945 (define_insn_and_split "*snedi_zero_trunc"
946   [(set (match_operand:SI 0 "register_operand" "=&r")
947         (ne:SI (match_operand:DI 1 "register_operand" "r")
948                (const_int 0)))]
949   "TARGET_ARCH64"
950   "#"
951   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
952   [(set (match_dup 0) (const_int 0))
953    (set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
954                                               (const_int 0))
955                                        (const_int 1)
956                                        (match_dup 0)))]
957   ""
958   [(set_attr "length" "2")])
959
960 (define_insn_and_split "*seqsi_zero"
961   [(set (match_operand:SI 0 "register_operand" "=r")
962         (eq:SI (match_operand:SI 1 "register_operand" "r")
963                (const_int 0)))
964    (clobber (reg:CC 100))]
965   ""
966   "#"
967   ""
968   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
969                                            (const_int 0)))
970    (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
971   ""
972   [(set_attr "length" "2")])
973
974 (define_insn_and_split "*neg_seqsi_zero"
975   [(set (match_operand:SI 0 "register_operand" "=r")
976         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
977                        (const_int 0))))
978    (clobber (reg:CC 100))]
979   ""
980   "#"
981   ""
982   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
983                                            (const_int 0)))
984    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
985   ""
986   [(set_attr "length" "2")])
987
988 (define_insn_and_split "*seqsi_zero_extend"
989   [(set (match_operand:DI 0 "register_operand" "=r")
990         (eq:DI (match_operand:SI 1 "register_operand" "r")
991                (const_int 0)))
992    (clobber (reg:CC 100))]
993   "TARGET_ARCH64"
994   "#"
995   "&& 1"
996   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
997                                                      (match_dup 1))
998                                            (const_int 0)))
999    (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
1000                                                           (const_int -1))
1001                                                 (ltu:SI (reg:CC_NOOV 100)
1002                                                         (const_int 0)))))]
1003   ""
1004   [(set_attr "length" "2")])
1005
1006 (define_insn_and_split "*seqdi_zero"
1007   [(set (match_operand:DI 0 "register_operand" "=&r")
1008         (eq:DI (match_operand:DI 1 "register_operand" "r")
1009                (const_int 0)))]
1010   "TARGET_ARCH64"
1011   "#"
1012   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
1013   [(set (match_dup 0) (const_int 0))
1014    (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
1015                                               (const_int 0))
1016                                        (const_int 1)
1017                                        (match_dup 0)))]
1018   ""
1019   [(set_attr "length" "2")])
1020
1021 (define_insn_and_split "*neg_seqdi_zero"
1022   [(set (match_operand:DI 0 "register_operand" "=&r")
1023         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
1024                        (const_int 0))))]
1025   "TARGET_ARCH64"
1026   "#"
1027   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
1028   [(set (match_dup 0) (const_int 0))
1029    (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
1030                                               (const_int 0))
1031                                        (const_int -1)
1032                                        (match_dup 0)))]
1033   ""
1034   [(set_attr "length" "2")]) 
1035
1036 (define_insn_and_split "*seqdi_zero_trunc"
1037   [(set (match_operand:SI 0 "register_operand" "=&r")
1038         (eq:SI (match_operand:DI 1 "register_operand" "r")
1039                (const_int 0)))]
1040   "TARGET_ARCH64"
1041   "#"
1042   "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
1043   [(set (match_dup 0) (const_int 0))
1044    (set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
1045                                               (const_int 0))
1046                                        (const_int 1)
1047                                        (match_dup 0)))]
1048   ""
1049   [(set_attr "length" "2")])
1050
1051 ;; We can also do (x + (i == 0)) and related, so put them in.
1052 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1053 ;; versions for v9.
1054
1055 (define_insn_and_split "*x_plus_i_ne_0"
1056   [(set (match_operand:SI 0 "register_operand" "=r")
1057         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
1058                         (const_int 0))
1059                  (match_operand:SI 2 "register_operand" "r")))
1060    (clobber (reg:CC 100))]
1061   ""
1062   "#"
1063   ""
1064   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1065                                            (const_int 0)))
1066    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1067                                (match_dup 2)))]
1068   ""
1069   [(set_attr "length" "2")])
1070
1071 (define_insn_and_split "*x_minus_i_ne_0"
1072   [(set (match_operand:SI 0 "register_operand" "=r")
1073         (minus:SI (match_operand:SI 2 "register_operand" "r")
1074                   (ne:SI (match_operand:SI 1 "register_operand" "r")
1075                          (const_int 0))))
1076    (clobber (reg:CC 100))]
1077   ""
1078   "#"
1079   ""
1080   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1081                                            (const_int 0)))
1082    (set (match_dup 0) (minus:SI (match_dup 2)
1083                                 (ltu:SI (reg:CC 100) (const_int 0))))]
1084   ""
1085   [(set_attr "length" "2")])
1086
1087 (define_insn_and_split "*x_plus_i_eq_0"
1088   [(set (match_operand:SI 0 "register_operand" "=r")
1089         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1090                         (const_int 0))
1091                  (match_operand:SI 2 "register_operand" "r")))
1092    (clobber (reg:CC 100))]
1093   ""
1094   "#"
1095   ""
1096   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1097                                            (const_int 0)))
1098    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1099                                (match_dup 2)))]
1100   ""
1101   [(set_attr "length" "2")])
1102
1103 (define_insn_and_split "*x_minus_i_eq_0"
1104   [(set (match_operand:SI 0 "register_operand" "=r")
1105         (minus:SI (match_operand:SI 2 "register_operand" "r")
1106                   (eq:SI (match_operand:SI 1 "register_operand" "r")
1107                          (const_int 0))))
1108    (clobber (reg:CC 100))]
1109   ""
1110   "#"
1111   ""
1112   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1113                                            (const_int 0)))
1114    (set (match_dup 0) (minus:SI (match_dup 2)
1115                                 (geu:SI (reg:CC 100) (const_int 0))))]
1116   ""
1117   [(set_attr "length" "2")])
1118
1119 ;; We can also do GEU and LTU directly, but these operate after a compare.
1120 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1121 ;; versions for v9.
1122
1123 (define_insn "*sltu_insn"
1124   [(set (match_operand:SI 0 "register_operand" "=r")
1125         (ltu:SI (reg:CC 100) (const_int 0)))]
1126   ""
1127   "addx\t%%g0, 0, %0"
1128   [(set_attr "type" "ialuX")])
1129
1130 (define_insn "*neg_sltu_insn"
1131   [(set (match_operand:SI 0 "register_operand" "=r")
1132         (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1133   ""
1134   "subx\t%%g0, 0, %0"
1135   [(set_attr "type" "ialuX")])
1136
1137 ;; ??? Combine should canonicalize these next two to the same pattern.
1138 (define_insn "*neg_sltu_minus_x"
1139   [(set (match_operand:SI 0 "register_operand" "=r")
1140         (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1141                   (match_operand:SI 1 "arith_operand" "rI")))]
1142   ""
1143   "subx\t%%g0, %1, %0"
1144   [(set_attr "type" "ialuX")])
1145
1146 (define_insn "*neg_sltu_plus_x"
1147   [(set (match_operand:SI 0 "register_operand" "=r")
1148         (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1149                          (match_operand:SI 1 "arith_operand" "rI"))))]
1150   ""
1151   "subx\t%%g0, %1, %0"
1152   [(set_attr "type" "ialuX")])
1153
1154 (define_insn "*sgeu_insn"
1155   [(set (match_operand:SI 0 "register_operand" "=r")
1156         (geu:SI (reg:CC 100) (const_int 0)))]
1157   ""
1158   "subx\t%%g0, -1, %0"
1159   [(set_attr "type" "ialuX")])
1160
1161 (define_insn "*neg_sgeu_insn"
1162   [(set (match_operand:SI 0 "register_operand" "=r")
1163         (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1164   ""
1165   "addx\t%%g0, -1, %0"
1166   [(set_attr "type" "ialuX")])
1167
1168 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1169 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1170 ;; versions for v9.
1171
1172 (define_insn "*sltu_plus_x"
1173   [(set (match_operand:SI 0 "register_operand" "=r")
1174         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1175                  (match_operand:SI 1 "arith_operand" "rI")))]
1176   ""
1177   "addx\t%%g0, %1, %0"
1178   [(set_attr "type" "ialuX")])
1179
1180 (define_insn "*sltu_plus_x_plus_y"
1181   [(set (match_operand:SI 0 "register_operand" "=r")
1182         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1183                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1184                           (match_operand:SI 2 "arith_operand" "rI"))))]
1185   ""
1186   "addx\t%1, %2, %0"
1187   [(set_attr "type" "ialuX")])
1188
1189 (define_insn "*x_minus_sltu"
1190   [(set (match_operand:SI 0 "register_operand" "=r")
1191         (minus:SI (match_operand:SI 1 "register_operand" "r")
1192                   (ltu:SI (reg:CC 100) (const_int 0))))]
1193   ""
1194   "subx\t%1, 0, %0"
1195   [(set_attr "type" "ialuX")])
1196
1197 ;; ??? Combine should canonicalize these next two to the same pattern.
1198 (define_insn "*x_minus_y_minus_sltu"
1199   [(set (match_operand:SI 0 "register_operand" "=r")
1200         (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
1201                             (match_operand:SI 2 "arith_operand" "rI"))
1202                   (ltu:SI (reg:CC 100) (const_int 0))))]
1203   ""
1204   "subx\t%r1, %2, %0"
1205   [(set_attr "type" "ialuX")])
1206
1207 (define_insn "*x_minus_sltu_plus_y"
1208   [(set (match_operand:SI 0 "register_operand" "=r")
1209         (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
1210                   (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1211                            (match_operand:SI 2 "arith_operand" "rI"))))]
1212   ""
1213   "subx\t%r1, %2, %0"
1214   [(set_attr "type" "ialuX")])
1215
1216 (define_insn "*sgeu_plus_x"
1217   [(set (match_operand:SI 0 "register_operand" "=r")
1218         (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1219                  (match_operand:SI 1 "register_operand" "r")))]
1220   ""
1221   "subx\t%1, -1, %0"
1222   [(set_attr "type" "ialuX")])
1223
1224 (define_insn "*x_minus_sgeu"
1225   [(set (match_operand:SI 0 "register_operand" "=r")
1226         (minus:SI (match_operand:SI 1 "register_operand" "r")
1227                   (geu:SI (reg:CC 100) (const_int 0))))]
1228   ""
1229   "addx\t%1, -1, %0"
1230   [(set_attr "type" "ialuX")])
1231
1232 (define_split
1233   [(set (match_operand:SI 0 "register_operand" "")
1234         (match_operator:SI 2 "noov_compare_operator"
1235                            [(match_operand 1 "icc_or_fcc_register_operand" "")
1236                             (const_int 0)]))]
1237   "TARGET_V9
1238    && REGNO (operands[1]) == SPARC_ICC_REG
1239    && (GET_MODE (operands[1]) == CCXmode
1240        /* 32-bit LTU/GEU are better implemented using addx/subx.  */
1241        || (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))"
1242   [(set (match_dup 0) (const_int 0))
1243    (set (match_dup 0)
1244         (if_then_else:SI (match_op_dup:SI 2 [(match_dup 1) (const_int 0)])
1245                          (const_int 1)
1246                          (match_dup 0)))]
1247   "")
1248
1249 \f
1250 ;; These control RTL generation for conditional jump insns
1251
1252 ;; The quad-word fp compare library routines all return nonzero to indicate
1253 ;; true, which is different from the equivalent libgcc routines, so we must
1254 ;; handle them specially here.
1255
1256 (define_expand "beq"
1257   [(set (pc)
1258         (if_then_else (eq (match_dup 1) (const_int 0))
1259                       (label_ref (match_operand 0 "" ""))
1260                       (pc)))]
1261   ""
1262 {
1263   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1264       && GET_CODE (sparc_compare_op0) == REG
1265       && GET_MODE (sparc_compare_op0) == DImode)
1266     {
1267       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1268       DONE;
1269     }
1270   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1271     {
1272       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1273       emit_jump_insn (gen_bne (operands[0]));
1274       DONE;
1275     }
1276   operands[1] = gen_compare_reg (EQ);
1277 })
1278
1279 (define_expand "bne"
1280   [(set (pc)
1281         (if_then_else (ne (match_dup 1) (const_int 0))
1282                       (label_ref (match_operand 0 "" ""))
1283                       (pc)))]
1284   ""
1285 {
1286   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1287       && GET_CODE (sparc_compare_op0) == REG
1288       && GET_MODE (sparc_compare_op0) == DImode)
1289     {
1290       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1291       DONE;
1292     }
1293   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1294     {
1295       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1296       emit_jump_insn (gen_bne (operands[0]));
1297       DONE;
1298     }
1299   operands[1] = gen_compare_reg (NE);
1300 })
1301
1302 (define_expand "bgt"
1303   [(set (pc)
1304         (if_then_else (gt (match_dup 1) (const_int 0))
1305                       (label_ref (match_operand 0 "" ""))
1306                       (pc)))]
1307   ""
1308 {
1309   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1310       && GET_CODE (sparc_compare_op0) == REG
1311       && GET_MODE (sparc_compare_op0) == DImode)
1312     {
1313       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1314       DONE;
1315     }
1316   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1317     {
1318       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1319       emit_jump_insn (gen_bne (operands[0]));
1320       DONE;
1321     }
1322   operands[1] = gen_compare_reg (GT);
1323 })
1324
1325 (define_expand "bgtu"
1326   [(set (pc)
1327         (if_then_else (gtu (match_dup 1) (const_int 0))
1328                       (label_ref (match_operand 0 "" ""))
1329                       (pc)))]
1330   ""
1331 {
1332   operands[1] = gen_compare_reg (GTU);
1333 })
1334
1335 (define_expand "blt"
1336   [(set (pc)
1337         (if_then_else (lt (match_dup 1) (const_int 0))
1338                       (label_ref (match_operand 0 "" ""))
1339                       (pc)))]
1340   ""
1341 {
1342   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1343       && GET_CODE (sparc_compare_op0) == REG
1344       && GET_MODE (sparc_compare_op0) == DImode)
1345     {
1346       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1347       DONE;
1348     }
1349   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1350     {
1351       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1352       emit_jump_insn (gen_bne (operands[0]));
1353       DONE;
1354     }
1355   operands[1] = gen_compare_reg (LT);
1356 })
1357
1358 (define_expand "bltu"
1359   [(set (pc)
1360         (if_then_else (ltu (match_dup 1) (const_int 0))
1361                       (label_ref (match_operand 0 "" ""))
1362                       (pc)))]
1363   ""
1364 {
1365   operands[1] = gen_compare_reg (LTU);
1366 })
1367
1368 (define_expand "bge"
1369   [(set (pc)
1370         (if_then_else (ge (match_dup 1) (const_int 0))
1371                       (label_ref (match_operand 0 "" ""))
1372                       (pc)))]
1373   ""
1374 {
1375   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1376       && GET_CODE (sparc_compare_op0) == REG
1377       && GET_MODE (sparc_compare_op0) == DImode)
1378     {
1379       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1380       DONE;
1381     }
1382   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1383     {
1384       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1385       emit_jump_insn (gen_bne (operands[0]));
1386       DONE;
1387     }
1388   operands[1] = gen_compare_reg (GE);
1389 })
1390
1391 (define_expand "bgeu"
1392   [(set (pc)
1393         (if_then_else (geu (match_dup 1) (const_int 0))
1394                       (label_ref (match_operand 0 "" ""))
1395                       (pc)))]
1396   ""
1397 {
1398   operands[1] = gen_compare_reg (GEU);
1399 })
1400
1401 (define_expand "ble"
1402   [(set (pc)
1403         (if_then_else (le (match_dup 1) (const_int 0))
1404                       (label_ref (match_operand 0 "" ""))
1405                       (pc)))]
1406   ""
1407 {
1408   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1409       && GET_CODE (sparc_compare_op0) == REG
1410       && GET_MODE (sparc_compare_op0) == DImode)
1411     {
1412       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1413       DONE;
1414     }
1415   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1416     {
1417       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1418       emit_jump_insn (gen_bne (operands[0]));
1419       DONE;
1420     }
1421   operands[1] = gen_compare_reg (LE);
1422 })
1423
1424 (define_expand "bleu"
1425   [(set (pc)
1426         (if_then_else (leu (match_dup 1) (const_int 0))
1427                       (label_ref (match_operand 0 "" ""))
1428                       (pc)))]
1429   ""
1430 {
1431   operands[1] = gen_compare_reg (LEU);
1432 })
1433
1434 (define_expand "bunordered"
1435   [(set (pc)
1436         (if_then_else (unordered (match_dup 1) (const_int 0))
1437                       (label_ref (match_operand 0 "" ""))
1438                       (pc)))]
1439   ""
1440 {
1441   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1442     {
1443       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
1444                                 UNORDERED);
1445       emit_jump_insn (gen_beq (operands[0]));
1446       DONE;
1447     }
1448   operands[1] = gen_compare_reg (UNORDERED);
1449 })
1450
1451 (define_expand "bordered"
1452   [(set (pc)
1453         (if_then_else (ordered (match_dup 1) (const_int 0))
1454                       (label_ref (match_operand 0 "" ""))
1455                       (pc)))]
1456   ""
1457 {
1458   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1459     {
1460       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
1461       emit_jump_insn (gen_bne (operands[0]));
1462       DONE;
1463     }
1464   operands[1] = gen_compare_reg (ORDERED);
1465 })
1466
1467 (define_expand "bungt"
1468   [(set (pc)
1469         (if_then_else (ungt (match_dup 1) (const_int 0))
1470                       (label_ref (match_operand 0 "" ""))
1471                       (pc)))]
1472   ""
1473 {
1474   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1475     {
1476       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
1477       emit_jump_insn (gen_bgt (operands[0]));
1478       DONE;
1479     }
1480   operands[1] = gen_compare_reg (UNGT);
1481 })
1482
1483 (define_expand "bunlt"
1484   [(set (pc)
1485         (if_then_else (unlt (match_dup 1) (const_int 0))
1486                       (label_ref (match_operand 0 "" ""))
1487                       (pc)))]
1488   ""
1489 {
1490   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1491     {
1492       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
1493       emit_jump_insn (gen_bne (operands[0]));
1494       DONE;
1495     }
1496   operands[1] = gen_compare_reg (UNLT);
1497 })
1498
1499 (define_expand "buneq"
1500   [(set (pc)
1501         (if_then_else (uneq (match_dup 1) (const_int 0))
1502                       (label_ref (match_operand 0 "" ""))
1503                       (pc)))]
1504   ""
1505 {
1506   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1507     {
1508       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
1509       emit_jump_insn (gen_beq (operands[0]));
1510       DONE;
1511     }
1512   operands[1] = gen_compare_reg (UNEQ);
1513 })
1514
1515 (define_expand "bunge"
1516   [(set (pc)
1517         (if_then_else (unge (match_dup 1) (const_int 0))
1518                       (label_ref (match_operand 0 "" ""))
1519                       (pc)))]
1520   ""
1521 {
1522   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1523     {
1524       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
1525       emit_jump_insn (gen_bne (operands[0]));
1526       DONE;
1527     }
1528   operands[1] = gen_compare_reg (UNGE);
1529 })
1530
1531 (define_expand "bunle"
1532   [(set (pc)
1533         (if_then_else (unle (match_dup 1) (const_int 0))
1534                       (label_ref (match_operand 0 "" ""))
1535                       (pc)))]
1536   ""
1537 {
1538   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1539     {
1540       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
1541       emit_jump_insn (gen_bne (operands[0]));
1542       DONE;
1543     }
1544   operands[1] = gen_compare_reg (UNLE);
1545 })
1546
1547 (define_expand "bltgt"
1548   [(set (pc)
1549         (if_then_else (ltgt (match_dup 1) (const_int 0))
1550                       (label_ref (match_operand 0 "" ""))
1551                       (pc)))]
1552   ""
1553 {
1554   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1555     {
1556       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
1557       emit_jump_insn (gen_bne (operands[0]));
1558       DONE;
1559     }
1560   operands[1] = gen_compare_reg (LTGT);
1561 })
1562 \f
1563 ;; Now match both normal and inverted jump.
1564
1565 ;; XXX fpcmp nop braindamage
1566 (define_insn "*normal_branch"
1567   [(set (pc)
1568         (if_then_else (match_operator 0 "noov_compare_operator"
1569                                       [(reg 100) (const_int 0)])
1570                       (label_ref (match_operand 1 "" ""))
1571                       (pc)))]
1572   ""
1573 {
1574   return output_cbranch (operands[0], operands[1], 1, 0,
1575                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1576                          insn);
1577 }
1578   [(set_attr "type" "branch")
1579    (set_attr "branch_type" "icc")])
1580
1581 ;; XXX fpcmp nop braindamage
1582 (define_insn "*inverted_branch"
1583   [(set (pc)
1584         (if_then_else (match_operator 0 "noov_compare_operator"
1585                                       [(reg 100) (const_int 0)])
1586                       (pc)
1587                       (label_ref (match_operand 1 "" ""))))]
1588   ""
1589 {
1590   return output_cbranch (operands[0], operands[1], 1, 1,
1591                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1592                          insn);
1593 }
1594   [(set_attr "type" "branch")
1595    (set_attr "branch_type" "icc")])
1596
1597 ;; XXX fpcmp nop braindamage
1598 (define_insn "*normal_fp_branch"
1599   [(set (pc)
1600         (if_then_else (match_operator 1 "comparison_operator"
1601                                       [(match_operand:CCFP 0 "fcc_register_operand" "c")
1602                                        (const_int 0)])
1603                       (label_ref (match_operand 2 "" ""))
1604                       (pc)))]
1605   ""
1606 {
1607   return output_cbranch (operands[1], operands[2], 2, 0,
1608                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1609                          insn);
1610 }
1611   [(set_attr "type" "branch")
1612    (set_attr "branch_type" "fcc")])
1613
1614 ;; XXX fpcmp nop braindamage
1615 (define_insn "*inverted_fp_branch"
1616   [(set (pc)
1617         (if_then_else (match_operator 1 "comparison_operator"
1618                                       [(match_operand:CCFP 0 "fcc_register_operand" "c")
1619                                        (const_int 0)])
1620                       (pc)
1621                       (label_ref (match_operand 2 "" ""))))]
1622   ""
1623 {
1624   return output_cbranch (operands[1], operands[2], 2, 1,
1625                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1626                          insn);
1627 }
1628   [(set_attr "type" "branch")
1629    (set_attr "branch_type" "fcc")])
1630
1631 ;; XXX fpcmp nop braindamage
1632 (define_insn "*normal_fpe_branch"
1633   [(set (pc)
1634         (if_then_else (match_operator 1 "comparison_operator"
1635                                       [(match_operand:CCFPE 0 "fcc_register_operand" "c")
1636                                        (const_int 0)])
1637                       (label_ref (match_operand 2 "" ""))
1638                       (pc)))]
1639   ""
1640 {
1641   return output_cbranch (operands[1], operands[2], 2, 0,
1642                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1643                          insn);
1644 }
1645   [(set_attr "type" "branch")
1646    (set_attr "branch_type" "fcc")])
1647
1648 ;; XXX fpcmp nop braindamage
1649 (define_insn "*inverted_fpe_branch"
1650   [(set (pc)
1651         (if_then_else (match_operator 1 "comparison_operator"
1652                                       [(match_operand:CCFPE 0 "fcc_register_operand" "c")
1653                                        (const_int 0)])
1654                       (pc)
1655                       (label_ref (match_operand 2 "" ""))))]
1656   ""
1657 {
1658   return output_cbranch (operands[1], operands[2], 2, 1,
1659                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1660                          insn);
1661 }
1662   [(set_attr "type" "branch")
1663    (set_attr "branch_type" "fcc")])
1664
1665 ;; SPARC V9-specific jump insns.  None of these are guaranteed to be
1666 ;; in the architecture.
1667
1668 ;; There are no 32 bit brreg insns.
1669
1670 ;; XXX
1671 (define_insn "*normal_int_branch_sp64"
1672   [(set (pc)
1673         (if_then_else (match_operator 0 "v9_register_compare_operator"
1674                                       [(match_operand:DI 1 "register_operand" "r")
1675                                        (const_int 0)])
1676                       (label_ref (match_operand 2 "" ""))
1677                       (pc)))]
1678   "TARGET_ARCH64"
1679 {
1680   return output_v9branch (operands[0], operands[2], 1, 2, 0,
1681                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1682                           insn);
1683 }
1684   [(set_attr "type" "branch")
1685    (set_attr "branch_type" "reg")])
1686
1687 ;; XXX
1688 (define_insn "*inverted_int_branch_sp64"
1689   [(set (pc)
1690         (if_then_else (match_operator 0 "v9_register_compare_operator"
1691                                       [(match_operand:DI 1 "register_operand" "r")
1692                                        (const_int 0)])
1693                       (pc)
1694                       (label_ref (match_operand 2 "" ""))))]
1695   "TARGET_ARCH64"
1696 {
1697   return output_v9branch (operands[0], operands[2], 1, 2, 1,
1698                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1699                           insn);
1700 }
1701   [(set_attr "type" "branch")
1702    (set_attr "branch_type" "reg")])
1703
1704
1705 (define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
1706
1707 ;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
1708 ;; value subject to a PC-relative relocation.  Operand 2 is a helper function
1709 ;; that adds the PC value at the call point to operand 0.
1710
1711 (define_insn "load_pcrel_sym<P:mode>"
1712   [(set (match_operand:P 0 "register_operand" "=r")
1713         (unspec:P [(match_operand:P 1 "symbolic_operand" "")
1714                    (match_operand:P 2 "call_address_operand" "")] UNSPEC_LOAD_PCREL_SYM))
1715    (clobber (reg:P 15))]
1716   ""
1717 {
1718   if (flag_delayed_branch)
1719     return "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\t add\t%0, %%lo(%a1+4), %0";
1720   else
1721     return "sethi\t%%hi(%a1-8), %0\n\tadd\t%0, %%lo(%a1-4), %0\n\tcall\t%a2\n\t nop";
1722 }
1723   [(set (attr "type") (const_string "multi"))
1724    (set (attr "length")
1725         (if_then_else (eq_attr "delayed_branch" "true")
1726                       (const_int 3)
1727                       (const_int 4)))])
1728
1729
1730 ;; Integer move instructions
1731
1732 (define_expand "movqi"
1733   [(set (match_operand:QI 0 "nonimmediate_operand" "")
1734         (match_operand:QI 1 "general_operand" ""))]
1735   ""
1736 {
1737   if (sparc_expand_move (QImode, operands))
1738     DONE;
1739 })
1740
1741 (define_insn "*movqi_insn"
1742   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
1743         (match_operand:QI 1 "input_operand"   "rI,m,rJ"))]
1744   "(register_operand (operands[0], QImode)
1745     || register_or_zero_operand (operands[1], QImode))"
1746   "@
1747    mov\t%1, %0
1748    ldub\t%1, %0
1749    stb\t%r1, %0"
1750   [(set_attr "type" "*,load,store")
1751    (set_attr "us3load_type" "*,3cycle,*")])
1752
1753 (define_expand "movhi"
1754   [(set (match_operand:HI 0 "nonimmediate_operand" "")
1755         (match_operand:HI 1 "general_operand" ""))]
1756   ""
1757 {
1758   if (sparc_expand_move (HImode, operands))
1759     DONE;
1760 })
1761
1762 (define_insn "*movhi_insn"
1763   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1764         (match_operand:HI 1 "input_operand"   "rI,K,m,rJ"))]
1765   "(register_operand (operands[0], HImode)
1766     || register_or_zero_operand (operands[1], HImode))"
1767   "@
1768    mov\t%1, %0
1769    sethi\t%%hi(%a1), %0
1770    lduh\t%1, %0
1771    sth\t%r1, %0"
1772   [(set_attr "type" "*,*,load,store")
1773    (set_attr "us3load_type" "*,*,3cycle,*")])
1774
1775 ;; We always work with constants here.
1776 (define_insn "*movhi_lo_sum"
1777   [(set (match_operand:HI 0 "register_operand" "=r")
1778         (ior:HI (match_operand:HI 1 "register_operand" "%r")
1779                 (match_operand:HI 2 "small_int_operand" "I")))]
1780   ""
1781   "or\t%1, %2, %0")
1782
1783 (define_expand "movsi"
1784   [(set (match_operand:SI 0 "nonimmediate_operand" "")
1785         (match_operand:SI 1 "general_operand" ""))]
1786   ""
1787 {
1788   if (sparc_expand_move (SImode, operands))
1789     DONE;
1790 })
1791
1792 (define_insn "*movsi_insn"
1793   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,!f,!f,!m,d")
1794         (match_operand:SI 1 "input_operand"   "rI,K,m,rJ,f,m,f,J"))]
1795   "(register_operand (operands[0], SImode)
1796     || register_or_zero_operand (operands[1], SImode))"
1797   "@
1798    mov\t%1, %0
1799    sethi\t%%hi(%a1), %0
1800    ld\t%1, %0
1801    st\t%r1, %0
1802    fmovs\t%1, %0
1803    ld\t%1, %0
1804    st\t%1, %0
1805    fzeros\t%0"
1806   [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga")])
1807
1808 (define_insn "*movsi_lo_sum"
1809   [(set (match_operand:SI 0 "register_operand" "=r")
1810         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1811                    (match_operand:SI 2 "immediate_operand" "in")))]
1812   ""
1813   "or\t%1, %%lo(%a2), %0")
1814
1815 (define_insn "*movsi_high"
1816   [(set (match_operand:SI 0 "register_operand" "=r")
1817         (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
1818   ""
1819   "sethi\t%%hi(%a1), %0")
1820
1821 ;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
1822 ;; so that CSE won't optimize the address computation away.
1823 (define_insn "movsi_lo_sum_pic"
1824   [(set (match_operand:SI 0 "register_operand" "=r")
1825         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1826                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
1827   "flag_pic"
1828   "or\t%1, %%lo(%a2), %0")
1829
1830 (define_insn "movsi_high_pic"
1831   [(set (match_operand:SI 0 "register_operand" "=r")
1832         (high:SI (unspec:SI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
1833   "flag_pic && check_pic (1)"
1834   "sethi\t%%hi(%a1), %0")
1835
1836 (define_expand "movsi_pic_label_ref"
1837   [(set (match_dup 3) (high:SI
1838      (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1839                  (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1840    (set (match_dup 4) (lo_sum:SI (match_dup 3)
1841      (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1842    (set (match_operand:SI 0 "register_operand" "=r")
1843         (minus:SI (match_dup 5) (match_dup 4)))]
1844   "flag_pic"
1845 {
1846   current_function_uses_pic_offset_table = 1;
1847   operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
1848   if (no_new_pseudos)
1849     {
1850       operands[3] = operands[0];
1851       operands[4] = operands[0];
1852     }
1853   else
1854     {
1855       operands[3] = gen_reg_rtx (SImode);
1856       operands[4] = gen_reg_rtx (SImode);
1857     }
1858   operands[5] = pic_offset_table_rtx;
1859 })
1860
1861 (define_insn "*movsi_high_pic_label_ref"
1862   [(set (match_operand:SI 0 "register_operand" "=r")
1863       (high:SI
1864         (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1865                     (match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1866   "flag_pic"
1867   "sethi\t%%hi(%a2-(%a1-.)), %0")
1868
1869 (define_insn "*movsi_lo_sum_pic_label_ref"
1870   [(set (match_operand:SI 0 "register_operand" "=r")
1871       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1872         (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
1873                     (match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1874   "flag_pic"
1875   "or\t%1, %%lo(%a3-(%a2-.)), %0")
1876
1877 ;; Set up the PIC register for VxWorks.
1878
1879 (define_expand "vxworks_load_got"
1880   [(set (match_dup 0)
1881         (high:SI (match_dup 1)))
1882    (set (match_dup 0)
1883         (mem:SI (lo_sum:SI (match_dup 0) (match_dup 1))))
1884    (set (match_dup 0)
1885         (mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))]
1886   "TARGET_VXWORKS_RTP"
1887 {
1888   operands[0] = pic_offset_table_rtx;
1889   operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE);
1890   operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX);
1891 })
1892
1893 (define_expand "movdi"
1894   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1895         (match_operand:DI 1 "general_operand" ""))]
1896   ""
1897 {
1898   if (sparc_expand_move (DImode, operands))
1899     DONE;
1900 })
1901
1902 ;; Be careful, fmovd does not exist when !v9.
1903 ;; We match MEM moves directly when we have correct even
1904 ;; numbered registers, but fall into splits otherwise.
1905 ;; The constraint ordering here is really important to
1906 ;; avoid insane problems in reload, especially for patterns
1907 ;; of the form:
1908 ;;
1909 ;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
1910 ;;                       (const_int -5016)))
1911 ;;      (reg:DI 2 %g2))
1912 ;;
1913
1914 (define_insn "*movdi_insn_sp32"
1915   [(set (match_operand:DI 0 "nonimmediate_operand"
1916                                 "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
1917         (match_operand:DI 1 "input_operand"
1918                                 " J,U,T,r,o,i,r, f, T, o, f, f"))]
1919   "! TARGET_V9
1920    && (register_operand (operands[0], DImode)
1921        || register_or_zero_operand (operands[1], DImode))"
1922   "@
1923    #
1924    std\t%1, %0
1925    ldd\t%1, %0
1926    #
1927    #
1928    #
1929    #
1930    std\t%1, %0
1931    ldd\t%1, %0
1932    #
1933    #
1934    #"
1935   [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
1936    (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
1937
1938 (define_insn "*movdi_insn_sp32_v9"
1939   [(set (match_operand:DI 0 "nonimmediate_operand"
1940                                         "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
1941         (match_operand:DI 1 "input_operand"
1942                                         " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
1943   "! TARGET_ARCH64
1944    && TARGET_V9
1945    && (register_operand (operands[0], DImode)
1946        || register_or_zero_operand (operands[1], DImode))"
1947   "@
1948    stx\t%%g0, %0
1949    #
1950    std\t%1, %0
1951    ldd\t%1, %0
1952    #
1953    #
1954    #
1955    #
1956    std\t%1, %0
1957    ldd\t%1, %0
1958    #
1959    #
1960    fmovd\\t%1, %0
1961    ldd\\t%1, %0
1962    std\\t%1, %0"
1963   [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
1964    (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
1965    (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
1966
1967 (define_insn "*movdi_insn_sp64"
1968   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b")
1969         (match_operand:DI 1 "input_operand"   "rI,N,m,rJ,e,W,e,J"))]
1970   "TARGET_ARCH64
1971    && (register_operand (operands[0], DImode)
1972        || register_or_zero_operand (operands[1], DImode))"
1973   "@
1974    mov\t%1, %0
1975    sethi\t%%hi(%a1), %0
1976    ldx\t%1, %0
1977    stx\t%r1, %0
1978    fmovd\t%1, %0
1979    ldd\t%1, %0
1980    std\t%1, %0
1981    fzero\t%0"
1982   [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga")
1983    (set_attr "fptype" "*,*,*,*,double,*,*,double")])
1984
1985 (define_expand "movdi_pic_label_ref"
1986   [(set (match_dup 3) (high:DI
1987      (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
1988                  (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1989    (set (match_dup 4) (lo_sum:DI (match_dup 3)
1990      (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1991    (set (match_operand:DI 0 "register_operand" "=r")
1992         (minus:DI (match_dup 5) (match_dup 4)))]
1993   "TARGET_ARCH64 && flag_pic"
1994 {
1995   current_function_uses_pic_offset_table = 1;
1996   operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
1997   if (no_new_pseudos)
1998     {
1999       operands[3] = operands[0];
2000       operands[4] = operands[0];
2001     }
2002   else
2003     {
2004       operands[3] = gen_reg_rtx (DImode);
2005       operands[4] = gen_reg_rtx (DImode);
2006     }
2007   operands[5] = pic_offset_table_rtx;
2008 })
2009
2010 (define_insn "*movdi_high_pic_label_ref"
2011   [(set (match_operand:DI 0 "register_operand" "=r")
2012         (high:DI
2013           (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2014                       (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2015   "TARGET_ARCH64 && flag_pic"
2016   "sethi\t%%hi(%a2-(%a1-.)), %0")
2017
2018 (define_insn "*movdi_lo_sum_pic_label_ref"
2019   [(set (match_operand:DI 0 "register_operand" "=r")
2020       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2021         (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2022                     (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2023   "TARGET_ARCH64 && flag_pic"
2024   "or\t%1, %%lo(%a3-(%a2-.)), %0")
2025
2026 ;; SPARC-v9 code model support insns.  See sparc_emit_set_symbolic_const64
2027 ;; in sparc.c to see what is going on here... PIC stuff comes first.
2028
2029 (define_insn "movdi_lo_sum_pic"
2030   [(set (match_operand:DI 0 "register_operand" "=r")
2031         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2032                    (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
2033   "TARGET_ARCH64 && flag_pic"
2034   "or\t%1, %%lo(%a2), %0")
2035
2036 (define_insn "movdi_high_pic"
2037   [(set (match_operand:DI 0 "register_operand" "=r")
2038         (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
2039   "TARGET_ARCH64 && flag_pic && check_pic (1)"
2040   "sethi\t%%hi(%a1), %0")
2041
2042 (define_insn "*sethi_di_medlow_embmedany_pic"
2043   [(set (match_operand:DI 0 "register_operand" "=r")
2044         (high:DI (match_operand:DI 1 "medium_pic_operand" "")))]
2045   "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2046   "sethi\t%%hi(%a1), %0")
2047
2048 (define_insn "*sethi_di_medlow"
2049   [(set (match_operand:DI 0 "register_operand" "=r")
2050         (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2051   "TARGET_CM_MEDLOW && check_pic (1)"
2052   "sethi\t%%hi(%a1), %0")
2053
2054 (define_insn "*losum_di_medlow"
2055   [(set (match_operand:DI 0 "register_operand" "=r")
2056         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2057                    (match_operand:DI 2 "symbolic_operand" "")))]
2058   "TARGET_CM_MEDLOW"
2059   "or\t%1, %%lo(%a2), %0")
2060
2061 (define_insn "seth44"
2062   [(set (match_operand:DI 0 "register_operand" "=r")
2063         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
2064   "TARGET_CM_MEDMID"
2065   "sethi\t%%h44(%a1), %0")
2066
2067 (define_insn "setm44"
2068   [(set (match_operand:DI 0 "register_operand" "=r")
2069         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2070                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
2071   "TARGET_CM_MEDMID"
2072   "or\t%1, %%m44(%a2), %0")
2073
2074 (define_insn "setl44"
2075   [(set (match_operand:DI 0 "register_operand" "=r")
2076         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2077                    (match_operand:DI 2 "symbolic_operand" "")))]
2078   "TARGET_CM_MEDMID"
2079   "or\t%1, %%l44(%a2), %0")
2080
2081 (define_insn "sethh"
2082   [(set (match_operand:DI 0 "register_operand" "=r")
2083         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
2084   "TARGET_CM_MEDANY"
2085   "sethi\t%%hh(%a1), %0")
2086
2087 (define_insn "setlm"
2088   [(set (match_operand:DI 0 "register_operand" "=r")
2089         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
2090   "TARGET_CM_MEDANY"
2091   "sethi\t%%lm(%a1), %0")
2092
2093 (define_insn "sethm"
2094   [(set (match_operand:DI 0 "register_operand" "=r")
2095         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2096                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
2097   "TARGET_CM_MEDANY"
2098   "or\t%1, %%hm(%a2), %0")
2099
2100 (define_insn "setlo"
2101   [(set (match_operand:DI 0 "register_operand" "=r")
2102         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2103                    (match_operand:DI 2 "symbolic_operand" "")))]
2104   "TARGET_CM_MEDANY"
2105   "or\t%1, %%lo(%a2), %0")
2106
2107 (define_insn "embmedany_sethi"
2108   [(set (match_operand:DI 0 "register_operand" "=r")
2109         (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
2110   "TARGET_CM_EMBMEDANY && check_pic (1)"
2111   "sethi\t%%hi(%a1), %0")
2112
2113 (define_insn "embmedany_losum"
2114   [(set (match_operand:DI 0 "register_operand" "=r")
2115         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2116                    (match_operand:DI 2 "data_segment_operand" "")))]
2117   "TARGET_CM_EMBMEDANY"
2118   "add\t%1, %%lo(%a2), %0")
2119
2120 (define_insn "embmedany_brsum"
2121   [(set (match_operand:DI 0 "register_operand" "=r")
2122         (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
2123   "TARGET_CM_EMBMEDANY"
2124   "add\t%1, %_, %0")
2125
2126 (define_insn "embmedany_textuhi"
2127   [(set (match_operand:DI 0 "register_operand" "=r")
2128         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
2129   "TARGET_CM_EMBMEDANY && check_pic (1)"
2130   "sethi\t%%uhi(%a1), %0")
2131
2132 (define_insn "embmedany_texthi"
2133   [(set (match_operand:DI 0 "register_operand" "=r")
2134         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
2135   "TARGET_CM_EMBMEDANY && check_pic (1)"
2136   "sethi\t%%hi(%a1), %0")
2137
2138 (define_insn "embmedany_textulo"
2139   [(set (match_operand:DI 0 "register_operand" "=r")
2140         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2141                    (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
2142   "TARGET_CM_EMBMEDANY"
2143   "or\t%1, %%ulo(%a2), %0")
2144
2145 (define_insn "embmedany_textlo"
2146   [(set (match_operand:DI 0 "register_operand" "=r")
2147         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2148                    (match_operand:DI 2 "text_segment_operand" "")))]
2149   "TARGET_CM_EMBMEDANY"
2150   "or\t%1, %%lo(%a2), %0")
2151
2152 ;; Now some patterns to help reload out a bit.
2153 (define_expand "reload_indi"
2154   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2155               (match_operand:DI 1 "immediate_operand" "")
2156               (match_operand:TI 2 "register_operand" "=&r")])]
2157   "(TARGET_CM_MEDANY
2158     || TARGET_CM_EMBMEDANY)
2159    && ! flag_pic"
2160 {
2161   sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2162   DONE;
2163 })
2164
2165 (define_expand "reload_outdi"
2166   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2167               (match_operand:DI 1 "immediate_operand" "")
2168               (match_operand:TI 2 "register_operand" "=&r")])]
2169   "(TARGET_CM_MEDANY
2170     || TARGET_CM_EMBMEDANY)
2171    && ! flag_pic"
2172 {
2173   sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2174   DONE;
2175 })
2176
2177 ;; Split up putting CONSTs and REGs into DI regs when !arch64
2178 (define_split
2179   [(set (match_operand:DI 0 "register_operand" "")
2180         (match_operand:DI 1 "const_int_operand" ""))]
2181   "! TARGET_ARCH64 && reload_completed"
2182   [(clobber (const_int 0))]
2183 {
2184 #if HOST_BITS_PER_WIDE_INT == 32
2185   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2186                         (INTVAL (operands[1]) < 0) ?
2187                         constm1_rtx :
2188                         const0_rtx));
2189   emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2190                         operands[1]));
2191 #else
2192   unsigned int low, high;
2193
2194   low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
2195   high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
2196   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
2197
2198   /* Slick... but this trick loses if this subreg constant part
2199      can be done in one insn.  */
2200   if (low == high
2201       && ! SPARC_SETHI32_P (high)
2202       && ! SPARC_SIMM13_P (high))
2203     emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2204                           gen_highpart (SImode, operands[0])));
2205   else
2206     emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
2207 #endif
2208   DONE;
2209 })
2210
2211 (define_split
2212   [(set (match_operand:DI 0 "register_operand" "")
2213         (match_operand:DI 1 "const_double_operand" ""))]
2214   "reload_completed
2215    && (! TARGET_V9
2216        || (! TARGET_ARCH64
2217            && ((GET_CODE (operands[0]) == REG
2218                 && REGNO (operands[0]) < 32)
2219                || (GET_CODE (operands[0]) == SUBREG
2220                    && GET_CODE (SUBREG_REG (operands[0])) == REG
2221                    && REGNO (SUBREG_REG (operands[0])) < 32))))"
2222   [(clobber (const_int 0))]
2223 {
2224   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2225                         GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2226
2227   /* Slick... but this trick loses if this subreg constant part
2228      can be done in one insn.  */
2229   if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2230       && ! SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
2231       && ! SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1])))
2232     {
2233       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2234                             gen_highpart (SImode, operands[0])));
2235     }
2236   else
2237     {
2238       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2239                             GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2240     }
2241   DONE;
2242 })
2243
2244 (define_split
2245   [(set (match_operand:DI 0 "register_operand" "")
2246         (match_operand:DI 1 "register_operand" ""))]
2247   "reload_completed
2248    && (! TARGET_V9
2249        || (! TARGET_ARCH64
2250            && ((GET_CODE (operands[0]) == REG
2251                 && REGNO (operands[0]) < 32)
2252                || (GET_CODE (operands[0]) == SUBREG
2253                    && GET_CODE (SUBREG_REG (operands[0])) == REG
2254                    && REGNO (SUBREG_REG (operands[0])) < 32))))"
2255   [(clobber (const_int 0))]
2256 {
2257   rtx set_dest = operands[0];
2258   rtx set_src = operands[1];
2259   rtx dest1, dest2;
2260   rtx src1, src2;
2261
2262   dest1 = gen_highpart (SImode, set_dest);
2263   dest2 = gen_lowpart (SImode, set_dest);
2264   src1 = gen_highpart (SImode, set_src);
2265   src2 = gen_lowpart (SImode, set_src);
2266
2267   /* Now emit using the real source and destination we found, swapping
2268      the order if we detect overlap.  */
2269   if (reg_overlap_mentioned_p (dest1, src2))
2270     {
2271       emit_insn (gen_movsi (dest2, src2));
2272       emit_insn (gen_movsi (dest1, src1));
2273     }
2274   else
2275     {
2276       emit_insn (gen_movsi (dest1, src1));
2277       emit_insn (gen_movsi (dest2, src2));
2278     }
2279   DONE;
2280 })
2281
2282 ;; Now handle the cases of memory moves from/to non-even
2283 ;; DI mode register pairs.
2284 (define_split
2285   [(set (match_operand:DI 0 "register_operand" "")
2286         (match_operand:DI 1 "memory_operand" ""))]
2287   "(! TARGET_ARCH64
2288     && reload_completed
2289     && sparc_splitdi_legitimate (operands[0], operands[1]))"
2290   [(clobber (const_int 0))]
2291 {
2292   rtx word0 = adjust_address (operands[1], SImode, 0);
2293   rtx word1 = adjust_address (operands[1], SImode, 4);
2294   rtx high_part = gen_highpart (SImode, operands[0]);
2295   rtx low_part = gen_lowpart (SImode, operands[0]);
2296
2297   if (reg_overlap_mentioned_p (high_part, word1))
2298     {
2299       emit_insn (gen_movsi (low_part, word1));
2300       emit_insn (gen_movsi (high_part, word0));
2301     }
2302   else
2303     {
2304       emit_insn (gen_movsi (high_part, word0));
2305       emit_insn (gen_movsi (low_part, word1));
2306     }
2307   DONE;
2308 })
2309
2310 (define_split
2311   [(set (match_operand:DI 0 "memory_operand" "")
2312         (match_operand:DI 1 "register_operand" ""))]
2313   "(! TARGET_ARCH64
2314     && reload_completed
2315     && sparc_splitdi_legitimate (operands[1], operands[0]))"
2316   [(clobber (const_int 0))]
2317 {
2318   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
2319                         gen_highpart (SImode, operands[1])));
2320   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
2321                         gen_lowpart (SImode, operands[1])));
2322   DONE;
2323 })
2324
2325 (define_split
2326   [(set (match_operand:DI 0 "memory_operand" "")
2327         (match_operand:DI 1 "const_zero_operand" ""))]
2328   "reload_completed
2329    && (! TARGET_V9
2330        || (! TARGET_ARCH64
2331            && ! mem_min_alignment (operands[0], 8)))
2332    && offsettable_memref_p (operands[0])"
2333   [(clobber (const_int 0))]
2334 {
2335   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
2336   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
2337   DONE;
2338 })
2339
2340
2341 ;; Floating point and vector move instructions
2342
2343 ;; We don't define V1SI because SI should work just fine.
2344 (define_mode_macro V32 [SF V2HI V4QI])
2345
2346 ;; Yes, you guessed it right, the former movsf expander.
2347 (define_expand "mov<V32:mode>"
2348   [(set (match_operand:V32 0 "nonimmediate_operand" "")
2349         (match_operand:V32 1 "general_operand" ""))]
2350   "<V32:MODE>mode == SFmode || TARGET_VIS"
2351 {
2352   if (sparc_expand_move (<V32:MODE>mode, operands))
2353     DONE;
2354 })
2355
2356 (define_insn "*movsf_insn"
2357   [(set (match_operand:V32 0 "nonimmediate_operand" "=d,f,*r,*r,*r,f,*r,m,m")
2358         (match_operand:V32 1 "input_operand"        "GY,f,*rRY,Q,S,m,m,f,*rGY"))]
2359   "TARGET_FPU
2360    && (register_operand (operands[0], <V32:MODE>mode)
2361        || register_or_zero_operand (operands[1], <V32:MODE>mode))"
2362 {
2363   if (GET_CODE (operands[1]) == CONST_DOUBLE
2364       && (which_alternative == 2
2365           || which_alternative == 3
2366           || which_alternative == 4))
2367     {
2368       REAL_VALUE_TYPE r;
2369       long i;
2370
2371       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2372       REAL_VALUE_TO_TARGET_SINGLE (r, i);
2373       operands[1] = GEN_INT (i);
2374     }
2375
2376   switch (which_alternative)
2377     {
2378     case 0:
2379       return "fzeros\t%0";
2380     case 1:
2381       return "fmovs\t%1, %0";
2382     case 2:
2383       return "mov\t%1, %0";
2384     case 3:
2385       return "sethi\t%%hi(%a1), %0";
2386     case 4:
2387       return "#";
2388     case 5:
2389     case 6:
2390       return "ld\t%1, %0";
2391     case 7:
2392     case 8:
2393       return "st\t%r1, %0";
2394     default:
2395       gcc_unreachable ();
2396     }
2397 }
2398   [(set_attr "type" "fga,fpmove,*,*,*,fpload,load,fpstore,store")])
2399
2400 ;; Exactly the same as above, except that all `f' cases are deleted.
2401 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2402 ;; when -mno-fpu.
2403
2404 (define_insn "*movsf_insn_no_fpu"
2405   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
2406         (match_operand:SF 1 "input_operand"    "rR,Q,S,m,rG"))]
2407   "! TARGET_FPU
2408    && (register_operand (operands[0], SFmode)
2409        || register_or_zero_operand (operands[1], SFmode))"
2410 {
2411   if (GET_CODE (operands[1]) == CONST_DOUBLE
2412       && (which_alternative == 0
2413           || which_alternative == 1
2414           || which_alternative == 2))
2415     {
2416       REAL_VALUE_TYPE r;
2417       long i;
2418
2419       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2420       REAL_VALUE_TO_TARGET_SINGLE (r, i);
2421       operands[1] = GEN_INT (i);
2422     }
2423
2424   switch (which_alternative)
2425     {
2426     case 0:
2427       return "mov\t%1, %0";
2428     case 1:
2429       return "sethi\t%%hi(%a1), %0";
2430     case 2:
2431       return "#";
2432     case 3:
2433       return "ld\t%1, %0";
2434     case 4:
2435       return "st\t%r1, %0";
2436     default:
2437       gcc_unreachable ();
2438     }
2439 }
2440   [(set_attr "type" "*,*,*,load,store")])
2441
2442 ;; The following 3 patterns build SFmode constants in integer registers.
2443
2444 (define_insn "*movsf_lo_sum"
2445   [(set (match_operand:SF 0 "register_operand" "=r")
2446         (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
2447                    (match_operand:SF 2 "fp_const_high_losum_operand" "S")))]
2448   ""
2449 {
2450   REAL_VALUE_TYPE r;
2451   long i;
2452
2453   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
2454   REAL_VALUE_TO_TARGET_SINGLE (r, i);
2455   operands[2] = GEN_INT (i);
2456   return "or\t%1, %%lo(%a2), %0";
2457 })
2458
2459 (define_insn "*movsf_high"
2460   [(set (match_operand:SF 0 "register_operand" "=r")
2461         (high:SF (match_operand:SF 1 "fp_const_high_losum_operand" "S")))]
2462   ""
2463 {
2464   REAL_VALUE_TYPE r;
2465   long i;
2466
2467   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2468   REAL_VALUE_TO_TARGET_SINGLE (r, i);
2469   operands[1] = GEN_INT (i);
2470   return "sethi\t%%hi(%1), %0";
2471 })
2472
2473 (define_split
2474   [(set (match_operand:SF 0 "register_operand" "")
2475         (match_operand:SF 1 "fp_const_high_losum_operand" ""))]
2476   "REG_P (operands[0]) && REGNO (operands[0]) < 32"
2477   [(set (match_dup 0) (high:SF (match_dup 1)))
2478    (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
2479
2480 (define_mode_macro V64 [DF V2SI V4HI V8QI])
2481
2482 ;; Yes, you again guessed it right, the former movdf expander.
2483 (define_expand "mov<V64:mode>"
2484   [(set (match_operand:V64 0 "nonimmediate_operand" "")
2485         (match_operand:V64 1 "general_operand" ""))]
2486   "<V64:MODE>mode == DFmode || TARGET_VIS"
2487 {
2488   if (sparc_expand_move (<V64:MODE>mode, operands))
2489     DONE;
2490 })
2491
2492 ;; Be careful, fmovd does not exist when !v9.
2493 (define_insn "*movdf_insn_sp32"
2494   [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
2495         (match_operand:DF 1 "input_operand"    "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
2496   "TARGET_FPU
2497    && ! TARGET_V9
2498    && (register_operand (operands[0], DFmode)
2499        || register_or_zero_operand (operands[1], DFmode))"
2500   "@
2501   ldd\t%1, %0
2502   std\t%1, %0
2503   ldd\t%1, %0
2504   std\t%1, %0
2505   #
2506   #
2507   #
2508   #
2509   #
2510   #"
2511  [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
2512   (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
2513
2514 (define_insn "*movdf_insn_sp32_no_fpu"
2515   [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
2516         (match_operand:DF 1 "input_operand"    "T,U,G,ro,r"))]
2517   "! TARGET_FPU
2518    && ! TARGET_V9
2519    && (register_operand (operands[0], DFmode)
2520        || register_or_zero_operand (operands[1], DFmode))"
2521   "@
2522   ldd\t%1, %0
2523   std\t%1, %0
2524   #
2525   #
2526   #"
2527   [(set_attr "type" "load,store,*,*,*")
2528    (set_attr "length" "*,*,2,2,2")])
2529
2530 ;; We have available v9 double floats but not 64-bit integer registers.
2531 (define_insn "*movdf_insn_sp32_v9"
2532   [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,T,W,U,T,f,*r,o")
2533         (match_operand:V64 1 "input_operand" "GY,e,W#F,GY,e,T,U,o#F,*roGYF,*rGYf"))]
2534   "TARGET_FPU
2535    && TARGET_V9
2536    && ! TARGET_ARCH64
2537    && (register_operand (operands[0], <V64:MODE>mode)
2538        || register_or_zero_operand (operands[1], <V64:MODE>mode))"
2539   "@
2540   fzero\t%0
2541   fmovd\t%1, %0
2542   ldd\t%1, %0
2543   stx\t%r1, %0
2544   std\t%1, %0
2545   ldd\t%1, %0
2546   std\t%1, %0
2547   #
2548   #
2549   #"
2550   [(set_attr "type" "fga,fpmove,load,store,store,load,store,*,*,*")
2551    (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
2552    (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
2553
2554 (define_insn "*movdf_insn_sp32_v9_no_fpu"
2555   [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
2556         (match_operand:DF 1 "input_operand"    "T,U,G,ro,rG"))]
2557   "! TARGET_FPU
2558    && TARGET_V9
2559    && ! TARGET_ARCH64
2560    && (register_operand (operands[0], DFmode)
2561        || register_or_zero_operand (operands[1], DFmode))"
2562   "@
2563   ldd\t%1, %0
2564   std\t%1, %0
2565   stx\t%r1, %0
2566   #
2567   #"
2568   [(set_attr "type" "load,store,store,*,*")
2569    (set_attr "length" "*,*,*,2,2")])
2570
2571 ;; We have available both v9 double floats and 64-bit integer registers.
2572 (define_insn "*movdf_insn_sp64"
2573   [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,W,*r,*r,m,*r")
2574         (match_operand:V64 1 "input_operand"    "GY,e,W#F,e,*rGY,m,*rGY,F"))]
2575   "TARGET_FPU
2576    && TARGET_ARCH64
2577    && (register_operand (operands[0], <V64:MODE>mode)
2578        || register_or_zero_operand (operands[1], <V64:MODE>mode))"
2579   "@
2580   fzero\t%0
2581   fmovd\t%1, %0
2582   ldd\t%1, %0
2583   std\t%1, %0
2584   mov\t%r1, %0
2585   ldx\t%1, %0
2586   stx\t%r1, %0
2587   #"
2588   [(set_attr "type" "fga,fpmove,load,store,*,load,store,*")
2589    (set_attr "length" "*,*,*,*,*,*,*,2")
2590    (set_attr "fptype" "double,double,*,*,*,*,*,*")])
2591
2592 (define_insn "*movdf_insn_sp64_no_fpu"
2593   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
2594         (match_operand:DF 1 "input_operand"    "r,m,rG"))]
2595   "! TARGET_FPU
2596    && TARGET_ARCH64
2597    && (register_operand (operands[0], DFmode)
2598        || register_or_zero_operand (operands[1], DFmode))"
2599   "@
2600   mov\t%1, %0
2601   ldx\t%1, %0
2602   stx\t%r1, %0"
2603   [(set_attr "type" "*,load,store")])
2604
2605 ;; This pattern build DFmode constants in integer registers.
2606 (define_split
2607   [(set (match_operand:DF 0 "register_operand" "")
2608         (match_operand:DF 1 "const_double_operand" ""))]
2609   "TARGET_FPU
2610    && (GET_CODE (operands[0]) == REG
2611        && REGNO (operands[0]) < 32)
2612    && ! const_zero_operand(operands[1], DFmode)
2613    && reload_completed"
2614   [(clobber (const_int 0))]
2615 {
2616   REAL_VALUE_TYPE r;
2617   long l[2];
2618
2619   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2620   REAL_VALUE_TO_TARGET_DOUBLE (r, l);
2621   operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
2622
2623   if (TARGET_ARCH64)
2624     {
2625 #if HOST_BITS_PER_WIDE_INT == 32
2626       gcc_unreachable ();
2627 #else
2628       HOST_WIDE_INT val;
2629
2630       val = ((HOST_WIDE_INT)(unsigned long)l[1] |
2631              ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
2632       emit_insn (gen_movdi (operands[0], gen_int_mode (val, DImode)));
2633 #endif
2634     }
2635   else
2636     {
2637       emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2638                             gen_int_mode (l[0], SImode)));
2639
2640       /* Slick... but this trick loses if this subreg constant part
2641          can be done in one insn.  */
2642       if (l[1] == l[0]
2643           && ! SPARC_SETHI32_P (l[0])
2644           && ! SPARC_SIMM13_P (l[0]))
2645         {
2646           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2647                                 gen_highpart (SImode, operands[0])));
2648         }
2649       else
2650         {
2651           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2652                                 gen_int_mode (l[1], SImode)));
2653         }
2654     }
2655   DONE;
2656 })
2657
2658 ;; Ok, now the splits to handle all the multi insn and
2659 ;; mis-aligned memory address cases.
2660 ;; In these splits please take note that we must be
2661 ;; careful when V9 but not ARCH64 because the integer
2662 ;; register DFmode cases must be handled.
2663 (define_split
2664   [(set (match_operand:V64 0 "register_operand" "")
2665         (match_operand:V64 1 "register_operand" ""))]
2666   "(! TARGET_V9
2667     || (! TARGET_ARCH64
2668         && ((GET_CODE (operands[0]) == REG
2669              && REGNO (operands[0]) < 32)
2670             || (GET_CODE (operands[0]) == SUBREG
2671                 && GET_CODE (SUBREG_REG (operands[0])) == REG
2672                 && REGNO (SUBREG_REG (operands[0])) < 32))))
2673    && reload_completed"
2674   [(clobber (const_int 0))]
2675 {
2676   rtx set_dest = operands[0];
2677   rtx set_src = operands[1];
2678   rtx dest1, dest2;
2679   rtx src1, src2;
2680   enum machine_mode half_mode;
2681
2682   /* We can be expanded for DFmode or integral vector modes.  */
2683   if (<V64:MODE>mode == DFmode)
2684     half_mode = SFmode;
2685   else
2686     half_mode = SImode;
2687   
2688   dest1 = gen_highpart (half_mode, set_dest);
2689   dest2 = gen_lowpart (half_mode, set_dest);
2690   src1 = gen_highpart (half_mode, set_src);
2691   src2 = gen_lowpart (half_mode, set_src);
2692
2693   /* Now emit using the real source and destination we found, swapping
2694      the order if we detect overlap.  */
2695   if (reg_overlap_mentioned_p (dest1, src2))
2696     {
2697       emit_move_insn_1 (dest2, src2);
2698       emit_move_insn_1 (dest1, src1);
2699     }
2700   else
2701     {
2702       emit_move_insn_1 (dest1, src1);
2703       emit_move_insn_1 (dest2, src2);
2704     }
2705   DONE;
2706 })
2707
2708 (define_split
2709   [(set (match_operand:V64 0 "register_operand" "")
2710         (match_operand:V64 1 "memory_operand" ""))]
2711   "reload_completed
2712    && ! TARGET_ARCH64
2713    && (((REGNO (operands[0]) % 2) != 0)
2714        || ! mem_min_alignment (operands[1], 8))
2715    && offsettable_memref_p (operands[1])"
2716   [(clobber (const_int 0))]
2717 {
2718   enum machine_mode half_mode;
2719   rtx word0, word1;
2720
2721   /* We can be expanded for DFmode or integral vector modes.  */
2722   if (<V64:MODE>mode == DFmode)
2723     half_mode = SFmode;
2724   else
2725     half_mode = SImode;
2726
2727   word0 = adjust_address (operands[1], half_mode, 0);
2728   word1 = adjust_address (operands[1], half_mode, 4);
2729
2730   if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1))
2731     {
2732       emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
2733       emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
2734     }
2735   else
2736     {
2737       emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
2738       emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
2739     }
2740   DONE;
2741 })
2742
2743 (define_split
2744   [(set (match_operand:V64 0 "memory_operand" "")
2745         (match_operand:V64 1 "register_operand" ""))]
2746   "reload_completed
2747    && ! TARGET_ARCH64
2748    && (((REGNO (operands[1]) % 2) != 0)
2749        || ! mem_min_alignment (operands[0], 8))
2750    && offsettable_memref_p (operands[0])"
2751   [(clobber (const_int 0))]
2752 {
2753   enum machine_mode half_mode;
2754   rtx word0, word1;
2755
2756   /* We can be expanded for DFmode or integral vector modes.  */
2757   if (<V64:MODE>mode == DFmode)
2758     half_mode = SFmode;
2759   else
2760     half_mode = SImode;
2761
2762   word0 = adjust_address (operands[0], half_mode, 0);
2763   word1 = adjust_address (operands[0], half_mode, 4);
2764
2765   emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1]));
2766   emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1]));
2767   DONE;
2768 })
2769
2770 (define_split
2771   [(set (match_operand:V64 0 "memory_operand" "")
2772         (match_operand:V64 1 "const_zero_operand" ""))]
2773   "reload_completed
2774    && (! TARGET_V9
2775        || (! TARGET_ARCH64
2776            && ! mem_min_alignment (operands[0], 8)))
2777    && offsettable_memref_p (operands[0])"
2778   [(clobber (const_int 0))]
2779 {
2780   enum machine_mode half_mode;
2781   rtx dest1, dest2;
2782
2783   /* We can be expanded for DFmode or integral vector modes.  */
2784   if (<V64:MODE>mode == DFmode)
2785     half_mode = SFmode;
2786   else
2787     half_mode = SImode;
2788
2789   dest1 = adjust_address (operands[0], half_mode, 0);
2790   dest2 = adjust_address (operands[0], half_mode, 4);
2791
2792   emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
2793   emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
2794   DONE;
2795 })
2796
2797 (define_split
2798   [(set (match_operand:V64 0 "register_operand" "")
2799         (match_operand:V64 1 "const_zero_operand" ""))]
2800   "reload_completed
2801    && ! TARGET_ARCH64
2802    && ((GET_CODE (operands[0]) == REG
2803         && REGNO (operands[0]) < 32)
2804        || (GET_CODE (operands[0]) == SUBREG
2805            && GET_CODE (SUBREG_REG (operands[0])) == REG
2806            && REGNO (SUBREG_REG (operands[0])) < 32))"
2807   [(clobber (const_int 0))]
2808 {
2809   enum machine_mode half_mode;
2810   rtx set_dest = operands[0];
2811   rtx dest1, dest2;
2812
2813   /* We can be expanded for DFmode or integral vector modes.  */
2814   if (<V64:MODE>mode == DFmode)
2815     half_mode = SFmode;
2816   else
2817     half_mode = SImode;
2818
2819   dest1 = gen_highpart (half_mode, set_dest);
2820   dest2 = gen_lowpart (half_mode, set_dest);
2821   emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
2822   emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
2823   DONE;
2824 })
2825
2826 (define_expand "movtf"
2827   [(set (match_operand:TF 0 "nonimmediate_operand" "")
2828         (match_operand:TF 1 "general_operand" ""))]
2829   ""
2830 {
2831   if (sparc_expand_move (TFmode, operands))
2832     DONE;
2833 })
2834
2835 (define_insn "*movtf_insn_sp32"
2836   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,U,r")
2837         (match_operand:TF 1 "input_operand"    "G,oe,GeUr,o,roG"))]
2838   "TARGET_FPU
2839    && ! TARGET_ARCH64
2840    && (register_operand (operands[0], TFmode)
2841        || register_or_zero_operand (operands[1], TFmode))"
2842   "#"
2843   [(set_attr "length" "4")])
2844
2845 ;; Exactly the same as above, except that all `e' cases are deleted.
2846 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2847 ;; when -mno-fpu.
2848
2849 (define_insn "*movtf_insn_sp32_no_fpu"
2850   [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
2851         (match_operand:TF 1 "input_operand"    "G,o,U,roG,r"))]
2852   "! TARGET_FPU
2853    && ! TARGET_ARCH64
2854    && (register_operand (operands[0], TFmode)
2855        || register_or_zero_operand (operands[1], TFmode))"
2856   "#"
2857   [(set_attr "length" "4")])
2858
2859 (define_insn "*movtf_insn_sp64"
2860   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
2861         (match_operand:TF 1 "input_operand"    "G,oe,Ger,roG"))]
2862   "TARGET_FPU
2863    && TARGET_ARCH64
2864    && ! TARGET_HARD_QUAD
2865    && (register_operand (operands[0], TFmode)
2866        || register_or_zero_operand (operands[1], TFmode))"
2867   "#"
2868   [(set_attr "length" "2")])
2869
2870 (define_insn "*movtf_insn_sp64_hq"
2871   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
2872         (match_operand:TF 1 "input_operand"    "G,e,m,e,rG,roG"))]
2873   "TARGET_FPU
2874    && TARGET_ARCH64
2875    && TARGET_HARD_QUAD
2876    && (register_operand (operands[0], TFmode)
2877        || register_or_zero_operand (operands[1], TFmode))"
2878   "@
2879   #
2880   fmovq\t%1, %0
2881   ldq\t%1, %0
2882   stq\t%1, %0
2883   #
2884   #"
2885   [(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
2886    (set_attr "length" "2,*,*,*,2,2")])
2887
2888 (define_insn "*movtf_insn_sp64_no_fpu"
2889   [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
2890         (match_operand:TF 1 "input_operand"    "orG,rG"))]
2891   "! TARGET_FPU
2892    && TARGET_ARCH64
2893    && (register_operand (operands[0], TFmode)
2894        || register_or_zero_operand (operands[1], TFmode))"
2895   "#"
2896   [(set_attr "length" "2")])
2897
2898 ;; Now all the splits to handle multi-insn TF mode moves.
2899 (define_split
2900   [(set (match_operand:TF 0 "register_operand" "")
2901         (match_operand:TF 1 "register_operand" ""))]
2902   "reload_completed
2903    && (! TARGET_ARCH64
2904        || (TARGET_FPU
2905            && ! TARGET_HARD_QUAD)
2906        || ! fp_register_operand (operands[0], TFmode))"
2907   [(clobber (const_int 0))]
2908 {
2909   rtx set_dest = operands[0];
2910   rtx set_src = operands[1];
2911   rtx dest1, dest2;
2912   rtx src1, src2;
2913
2914   dest1 = gen_df_reg (set_dest, 0);
2915   dest2 = gen_df_reg (set_dest, 1);
2916   src1 = gen_df_reg (set_src, 0);
2917   src2 = gen_df_reg (set_src, 1);
2918
2919   /* Now emit using the real source and destination we found, swapping
2920      the order if we detect overlap.  */
2921   if (reg_overlap_mentioned_p (dest1, src2))
2922     {
2923       emit_insn (gen_movdf (dest2, src2));
2924       emit_insn (gen_movdf (dest1, src1));
2925     }
2926   else
2927     {
2928       emit_insn (gen_movdf (dest1, src1));
2929       emit_insn (gen_movdf (dest2, src2));
2930     }
2931   DONE;
2932 })
2933
2934 (define_split
2935   [(set (match_operand:TF 0 "nonimmediate_operand" "")
2936         (match_operand:TF 1 "const_zero_operand" ""))]
2937   "reload_completed"
2938   [(clobber (const_int 0))]
2939 {
2940   rtx set_dest = operands[0];
2941   rtx dest1, dest2;
2942
2943   switch (GET_CODE (set_dest))
2944     {
2945     case REG:
2946       dest1 = gen_df_reg (set_dest, 0);
2947       dest2 = gen_df_reg (set_dest, 1);
2948       break;
2949     case MEM:
2950       dest1 = adjust_address (set_dest, DFmode, 0);
2951       dest2 = adjust_address (set_dest, DFmode, 8);
2952       break;
2953     default:
2954       gcc_unreachable ();      
2955     }
2956
2957   emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
2958   emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
2959   DONE;
2960 })
2961
2962 (define_split
2963   [(set (match_operand:TF 0 "register_operand" "")
2964         (match_operand:TF 1 "memory_operand" ""))]
2965   "(reload_completed
2966     && offsettable_memref_p (operands[1])
2967     && (! TARGET_ARCH64
2968         || ! TARGET_HARD_QUAD
2969         || ! fp_register_operand (operands[0], TFmode)))"
2970   [(clobber (const_int 0))]
2971 {
2972   rtx word0 = adjust_address (operands[1], DFmode, 0);
2973   rtx word1 = adjust_address (operands[1], DFmode, 8);
2974   rtx set_dest, dest1, dest2;
2975
2976   set_dest = operands[0];
2977
2978   dest1 = gen_df_reg (set_dest, 0);
2979   dest2 = gen_df_reg (set_dest, 1);
2980
2981   /* Now output, ordering such that we don't clobber any registers
2982      mentioned in the address.  */
2983   if (reg_overlap_mentioned_p (dest1, word1))
2984
2985     {
2986       emit_insn (gen_movdf (dest2, word1));
2987       emit_insn (gen_movdf (dest1, word0));
2988     }
2989   else
2990    {
2991       emit_insn (gen_movdf (dest1, word0));
2992       emit_insn (gen_movdf (dest2, word1));
2993    }
2994   DONE;
2995 })
2996
2997 (define_split
2998   [(set (match_operand:TF 0 "memory_operand" "")
2999         (match_operand:TF 1 "register_operand" ""))]
3000   "(reload_completed
3001     && offsettable_memref_p (operands[0])
3002     && (! TARGET_ARCH64
3003         || ! TARGET_HARD_QUAD
3004         || ! fp_register_operand (operands[1], TFmode)))"
3005   [(clobber (const_int 0))]
3006 {
3007   rtx set_src = operands[1];
3008
3009   emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
3010                         gen_df_reg (set_src, 0)));
3011   emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
3012                         gen_df_reg (set_src, 1)));
3013   DONE;
3014 })
3015
3016
3017 ;; SPARC-V9 conditional move instructions.
3018
3019 ;; We can handle larger constants here for some flavors, but for now we keep
3020 ;; it simple and only allow those constants supported by all flavors.
3021 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3022 ;; 3 contains the constant if one is present, but we handle either for
3023 ;; generality (sparc.c puts a constant in operand 2).
3024
3025 (define_expand "movqicc"
3026   [(set (match_operand:QI 0 "register_operand" "")
3027         (if_then_else:QI (match_operand 1 "comparison_operator" "")
3028                          (match_operand:QI 2 "arith10_operand" "")
3029                          (match_operand:QI 3 "arith10_operand" "")))]
3030   "TARGET_V9"
3031 {
3032   enum rtx_code code = GET_CODE (operands[1]);
3033
3034   if (GET_MODE (sparc_compare_op0) == DImode
3035       && ! TARGET_ARCH64)
3036     FAIL;
3037
3038   if (sparc_compare_op1 == const0_rtx
3039       && GET_CODE (sparc_compare_op0) == REG
3040       && GET_MODE (sparc_compare_op0) == DImode
3041       && v9_regcmp_p (code))
3042     {
3043       operands[1] = gen_rtx_fmt_ee (code, DImode,
3044                              sparc_compare_op0, sparc_compare_op1);
3045     }
3046   else
3047     {
3048       rtx cc_reg = gen_compare_reg (code);
3049       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3050     }
3051 })
3052
3053 (define_expand "movhicc"
3054   [(set (match_operand:HI 0 "register_operand" "")
3055         (if_then_else:HI (match_operand 1 "comparison_operator" "")
3056                          (match_operand:HI 2 "arith10_operand" "")
3057                          (match_operand:HI 3 "arith10_operand" "")))]
3058   "TARGET_V9"
3059 {
3060   enum rtx_code code = GET_CODE (operands[1]);
3061
3062   if (GET_MODE (sparc_compare_op0) == DImode
3063       && ! TARGET_ARCH64)
3064     FAIL;
3065
3066   if (sparc_compare_op1 == const0_rtx
3067       && GET_CODE (sparc_compare_op0) == REG
3068       && GET_MODE (sparc_compare_op0) == DImode
3069       && v9_regcmp_p (code))
3070     {
3071       operands[1] = gen_rtx_fmt_ee (code, DImode,
3072                              sparc_compare_op0, sparc_compare_op1);
3073     }
3074   else
3075     {
3076       rtx cc_reg = gen_compare_reg (code);
3077       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3078     }
3079 })
3080
3081 (define_expand "movsicc"
3082   [(set (match_operand:SI 0 "register_operand" "")
3083         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3084                          (match_operand:SI 2 "arith10_operand" "")
3085                          (match_operand:SI 3 "arith10_operand" "")))]
3086   "TARGET_V9"
3087 {
3088   enum rtx_code code = GET_CODE (operands[1]);
3089   enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3090
3091   if (sparc_compare_op1 == const0_rtx
3092       && GET_CODE (sparc_compare_op0) == REG
3093       && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3094     {
3095       operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3096                              sparc_compare_op0, sparc_compare_op1);
3097     }
3098   else
3099     {
3100       rtx cc_reg = gen_compare_reg (code);
3101       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3102                                     cc_reg, const0_rtx);
3103     }
3104 })
3105
3106 (define_expand "movdicc"
3107   [(set (match_operand:DI 0 "register_operand" "")
3108         (if_then_else:DI (match_operand 1 "comparison_operator" "")
3109                          (match_operand:DI 2 "arith10_operand" "")
3110                          (match_operand:DI 3 "arith10_operand" "")))]
3111   "TARGET_ARCH64"
3112 {
3113   enum rtx_code code = GET_CODE (operands[1]);
3114
3115   if (sparc_compare_op1 == const0_rtx
3116       && GET_CODE (sparc_compare_op0) == REG
3117       && GET_MODE (sparc_compare_op0) == DImode
3118       && v9_regcmp_p (code))
3119     {
3120       operands[1] = gen_rtx_fmt_ee (code, DImode,
3121                              sparc_compare_op0, sparc_compare_op1);
3122     }
3123   else
3124     {
3125       rtx cc_reg = gen_compare_reg (code);
3126       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3127                                     cc_reg, const0_rtx);
3128     }
3129 })
3130
3131 (define_expand "movsfcc"
3132   [(set (match_operand:SF 0 "register_operand" "")
3133         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3134                          (match_operand:SF 2 "register_operand" "")
3135                          (match_operand:SF 3 "register_operand" "")))]
3136   "TARGET_V9 && TARGET_FPU"
3137 {
3138   enum rtx_code code = GET_CODE (operands[1]);
3139
3140   if (GET_MODE (sparc_compare_op0) == DImode
3141       && ! TARGET_ARCH64)
3142     FAIL;
3143
3144   if (sparc_compare_op1 == const0_rtx
3145       && GET_CODE (sparc_compare_op0) == REG
3146       && GET_MODE (sparc_compare_op0) == DImode
3147       && v9_regcmp_p (code))
3148     {
3149       operands[1] = gen_rtx_fmt_ee (code, DImode,
3150                              sparc_compare_op0, sparc_compare_op1);
3151     }
3152   else
3153     {
3154       rtx cc_reg = gen_compare_reg (code);
3155       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3156     }
3157 })
3158
3159 (define_expand "movdfcc"
3160   [(set (match_operand:DF 0 "register_operand" "")
3161         (if_then_else:DF (match_operand 1 "comparison_operator" "")
3162                          (match_operand:DF 2 "register_operand" "")
3163                          (match_operand:DF 3 "register_operand" "")))]
3164   "TARGET_V9 && TARGET_FPU"
3165 {
3166   enum rtx_code code = GET_CODE (operands[1]);
3167
3168   if (GET_MODE (sparc_compare_op0) == DImode
3169       && ! TARGET_ARCH64)
3170     FAIL;
3171
3172   if (sparc_compare_op1 == const0_rtx
3173       && GET_CODE (sparc_compare_op0) == REG
3174       && GET_MODE (sparc_compare_op0) == DImode
3175       && v9_regcmp_p (code))
3176     {
3177       operands[1] = gen_rtx_fmt_ee (code, DImode,
3178                              sparc_compare_op0, sparc_compare_op1);
3179     }
3180   else
3181     {
3182       rtx cc_reg = gen_compare_reg (code);
3183       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3184     }
3185 })
3186
3187 (define_expand "movtfcc"
3188   [(set (match_operand:TF 0 "register_operand" "")
3189         (if_then_else:TF (match_operand 1 "comparison_operator" "")
3190                          (match_operand:TF 2 "register_operand" "")
3191                          (match_operand:TF 3 "register_operand" "")))]
3192   "TARGET_V9 && TARGET_FPU"
3193 {
3194   enum rtx_code code = GET_CODE (operands[1]);
3195
3196   if (GET_MODE (sparc_compare_op0) == DImode
3197       && ! TARGET_ARCH64)
3198     FAIL;
3199
3200   if (sparc_compare_op1 == const0_rtx
3201       && GET_CODE (sparc_compare_op0) == REG
3202       && GET_MODE (sparc_compare_op0) == DImode
3203       && v9_regcmp_p (code))
3204     {
3205       operands[1] = gen_rtx_fmt_ee (code, DImode,
3206                              sparc_compare_op0, sparc_compare_op1);
3207     }
3208   else
3209     {
3210       rtx cc_reg = gen_compare_reg (code);
3211       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3212     }
3213 })
3214
3215 ;; Conditional move define_insns.
3216
3217 (define_insn "*movqi_cc_sp64"
3218   [(set (match_operand:QI 0 "register_operand" "=r,r")
3219         (if_then_else:QI (match_operator 1 "comparison_operator"
3220                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3221                                  (const_int 0)])
3222                          (match_operand:QI 3 "arith11_operand" "rL,0")
3223                          (match_operand:QI 4 "arith11_operand" "0,rL")))]
3224   "TARGET_V9"
3225   "@
3226    mov%C1\t%x2, %3, %0
3227    mov%c1\t%x2, %4, %0"
3228   [(set_attr "type" "cmove")])
3229
3230 (define_insn "*movhi_cc_sp64"
3231   [(set (match_operand:HI 0 "register_operand" "=r,r")
3232         (if_then_else:HI (match_operator 1 "comparison_operator"
3233                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3234                                  (const_int 0)])
3235                          (match_operand:HI 3 "arith11_operand" "rL,0")
3236                          (match_operand:HI 4 "arith11_operand" "0,rL")))]
3237   "TARGET_V9"
3238   "@
3239    mov%C1\t%x2, %3, %0
3240    mov%c1\t%x2, %4, %0"
3241   [(set_attr "type" "cmove")])
3242
3243 (define_insn "*movsi_cc_sp64"
3244   [(set (match_operand:SI 0 "register_operand" "=r,r")
3245         (if_then_else:SI (match_operator 1 "comparison_operator"
3246                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3247                                  (const_int 0)])
3248                          (match_operand:SI 3 "arith11_operand" "rL,0")
3249                          (match_operand:SI 4 "arith11_operand" "0,rL")))]
3250   "TARGET_V9"
3251   "@
3252    mov%C1\t%x2, %3, %0
3253    mov%c1\t%x2, %4, %0"
3254   [(set_attr "type" "cmove")])
3255
3256 (define_insn "*movdi_cc_sp64"
3257   [(set (match_operand:DI 0 "register_operand" "=r,r")
3258         (if_then_else:DI (match_operator 1 "comparison_operator"
3259                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3260                                  (const_int 0)])
3261                          (match_operand:DI 3 "arith11_operand" "rL,0")
3262                          (match_operand:DI 4 "arith11_operand" "0,rL")))]
3263   "TARGET_ARCH64"
3264   "@
3265    mov%C1\t%x2, %3, %0
3266    mov%c1\t%x2, %4, %0"
3267   [(set_attr "type" "cmove")])
3268
3269 (define_insn "*movdi_cc_sp64_trunc"
3270   [(set (match_operand:SI 0 "register_operand" "=r,r")
3271         (if_then_else:SI (match_operator 1 "comparison_operator"
3272                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3273                                  (const_int 0)])
3274                          (match_operand:SI 3 "arith11_operand" "rL,0")
3275                          (match_operand:SI 4 "arith11_operand" "0,rL")))]
3276   "TARGET_ARCH64"
3277   "@
3278    mov%C1\t%x2, %3, %0
3279    mov%c1\t%x2, %4, %0"
3280   [(set_attr "type" "cmove")])
3281
3282 (define_insn "*movsf_cc_sp64"
3283   [(set (match_operand:SF 0 "register_operand" "=f,f")
3284         (if_then_else:SF (match_operator 1 "comparison_operator"
3285                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3286                                  (const_int 0)])
3287                          (match_operand:SF 3 "register_operand" "f,0")
3288                          (match_operand:SF 4 "register_operand" "0,f")))]
3289   "TARGET_V9 && TARGET_FPU"
3290   "@
3291    fmovs%C1\t%x2, %3, %0
3292    fmovs%c1\t%x2, %4, %0"
3293   [(set_attr "type" "fpcmove")])
3294
3295 (define_insn "movdf_cc_sp64"
3296   [(set (match_operand:DF 0 "register_operand" "=e,e")
3297         (if_then_else:DF (match_operator 1 "comparison_operator"
3298                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3299                                  (const_int 0)])
3300                          (match_operand:DF 3 "register_operand" "e,0")
3301                          (match_operand:DF 4 "register_operand" "0,e")))]
3302   "TARGET_V9 && TARGET_FPU"
3303   "@
3304    fmovd%C1\t%x2, %3, %0
3305    fmovd%c1\t%x2, %4, %0"
3306   [(set_attr "type" "fpcmove")
3307    (set_attr "fptype" "double")])
3308
3309 (define_insn "*movtf_cc_hq_sp64"
3310   [(set (match_operand:TF 0 "register_operand" "=e,e")
3311         (if_then_else:TF (match_operator 1 "comparison_operator"
3312                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3313                                  (const_int 0)])
3314                          (match_operand:TF 3 "register_operand" "e,0")
3315                          (match_operand:TF 4 "register_operand" "0,e")))]
3316   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3317   "@
3318    fmovq%C1\t%x2, %3, %0
3319    fmovq%c1\t%x2, %4, %0"
3320   [(set_attr "type" "fpcmove")])
3321
3322 (define_insn_and_split "*movtf_cc_sp64"
3323   [(set (match_operand:TF 0 "register_operand" "=e,e")
3324         (if_then_else:TF (match_operator 1 "comparison_operator"
3325                             [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3326                              (const_int 0)])
3327                          (match_operand:TF 3 "register_operand" "e,0")
3328                          (match_operand:TF 4 "register_operand" "0,e")))]
3329   "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
3330   "#"
3331   "&& reload_completed"
3332   [(clobber (const_int 0))]
3333 {
3334   rtx set_dest = operands[0];
3335   rtx set_srca = operands[3];
3336   rtx set_srcb = operands[4];
3337   int third = rtx_equal_p (set_dest, set_srca);
3338   rtx dest1, dest2;
3339   rtx srca1, srca2, srcb1, srcb2;
3340
3341   dest1 = gen_df_reg (set_dest, 0);
3342   dest2 = gen_df_reg (set_dest, 1);
3343   srca1 = gen_df_reg (set_srca, 0);
3344   srca2 = gen_df_reg (set_srca, 1);
3345   srcb1 = gen_df_reg (set_srcb, 0);
3346   srcb2 = gen_df_reg (set_srcb, 1);
3347
3348   /* Now emit using the real source and destination we found, swapping
3349      the order if we detect overlap.  */
3350   if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3351       || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3352     {
3353       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3354       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3355     }
3356   else
3357     {
3358       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3359       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3360     }
3361   DONE;
3362 }
3363   [(set_attr "length" "2")])
3364
3365 (define_insn "*movqi_cc_reg_sp64"
3366   [(set (match_operand:QI 0 "register_operand" "=r,r")
3367         (if_then_else:QI (match_operator 1 "v9_register_compare_operator"
3368                                 [(match_operand:DI 2 "register_operand" "r,r")
3369                                  (const_int 0)])
3370                          (match_operand:QI 3 "arith10_operand" "rM,0")
3371                          (match_operand:QI 4 "arith10_operand" "0,rM")))]
3372   "TARGET_ARCH64"
3373   "@
3374    movr%D1\t%2, %r3, %0
3375    movr%d1\t%2, %r4, %0"
3376   [(set_attr "type" "cmove")])
3377
3378 (define_insn "*movhi_cc_reg_sp64"
3379   [(set (match_operand:HI 0 "register_operand" "=r,r")
3380         (if_then_else:HI (match_operator 1 "v9_register_compare_operator"
3381                                 [(match_operand:DI 2 "register_operand" "r,r")
3382                                  (const_int 0)])
3383                          (match_operand:HI 3 "arith10_operand" "rM,0")
3384                          (match_operand:HI 4 "arith10_operand" "0,rM")))]
3385   "TARGET_ARCH64"
3386   "@
3387    movr%D1\t%2, %r3, %0
3388    movr%d1\t%2, %r4, %0"
3389   [(set_attr "type" "cmove")])
3390
3391 (define_insn "*movsi_cc_reg_sp64"
3392   [(set (match_operand:SI 0 "register_operand" "=r,r")
3393         (if_then_else:SI (match_operator 1 "v9_register_compare_operator"
3394                                 [(match_operand:DI 2 "register_operand" "r,r")
3395                                  (const_int 0)])
3396                          (match_operand:SI 3 "arith10_operand" "rM,0")
3397                          (match_operand:SI 4 "arith10_operand" "0,rM")))]
3398   "TARGET_ARCH64"
3399   "@
3400    movr%D1\t%2, %r3, %0
3401    movr%d1\t%2, %r4, %0"
3402   [(set_attr "type" "cmove")])
3403
3404 (define_insn "*movdi_cc_reg_sp64"
3405   [(set (match_operand:DI 0 "register_operand" "=r,r")
3406         (if_then_else:DI (match_operator 1 "v9_register_compare_operator"
3407                                 [(match_operand:DI 2 "register_operand" "r,r")
3408                                  (const_int 0)])
3409                          (match_operand:DI 3 "arith10_operand" "rM,0")
3410                          (match_operand:DI 4 "arith10_operand" "0,rM")))]
3411   "TARGET_ARCH64"
3412   "@
3413    movr%D1\t%2, %r3, %0