OSDN Git Service

387b3405db5d5b1358ccfff779e8738b33695070
[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 (define_expand "movdi"
1878   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1879         (match_operand:DI 1 "general_operand" ""))]
1880   ""
1881 {
1882   if (sparc_expand_move (DImode, operands))
1883     DONE;
1884 })
1885
1886 ;; Be careful, fmovd does not exist when !v9.
1887 ;; We match MEM moves directly when we have correct even
1888 ;; numbered registers, but fall into splits otherwise.
1889 ;; The constraint ordering here is really important to
1890 ;; avoid insane problems in reload, especially for patterns
1891 ;; of the form:
1892 ;;
1893 ;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
1894 ;;                       (const_int -5016)))
1895 ;;      (reg:DI 2 %g2))
1896 ;;
1897
1898 (define_insn "*movdi_insn_sp32"
1899   [(set (match_operand:DI 0 "nonimmediate_operand"
1900                                 "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
1901         (match_operand:DI 1 "input_operand"
1902                                 " J,U,T,r,o,i,r, f, T, o, f, f"))]
1903   "! TARGET_V9
1904    && (register_operand (operands[0], DImode)
1905        || register_or_zero_operand (operands[1], DImode))"
1906   "@
1907    #
1908    std\t%1, %0
1909    ldd\t%1, %0
1910    #
1911    #
1912    #
1913    #
1914    std\t%1, %0
1915    ldd\t%1, %0
1916    #
1917    #
1918    #"
1919   [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
1920    (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
1921
1922 (define_insn "*movdi_insn_sp32_v9"
1923   [(set (match_operand:DI 0 "nonimmediate_operand"
1924                                         "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
1925         (match_operand:DI 1 "input_operand"
1926                                         " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
1927   "! TARGET_ARCH64
1928    && TARGET_V9
1929    && (register_operand (operands[0], DImode)
1930        || register_or_zero_operand (operands[1], DImode))"
1931   "@
1932    stx\t%%g0, %0
1933    #
1934    std\t%1, %0
1935    ldd\t%1, %0
1936    #
1937    #
1938    #
1939    #
1940    std\t%1, %0
1941    ldd\t%1, %0
1942    #
1943    #
1944    fmovd\\t%1, %0
1945    ldd\\t%1, %0
1946    std\\t%1, %0"
1947   [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
1948    (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
1949    (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
1950
1951 (define_insn "*movdi_insn_sp64"
1952   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b")
1953         (match_operand:DI 1 "input_operand"   "rI,N,m,rJ,e,W,e,J"))]
1954   "TARGET_ARCH64
1955    && (register_operand (operands[0], DImode)
1956        || register_or_zero_operand (operands[1], DImode))"
1957   "@
1958    mov\t%1, %0
1959    sethi\t%%hi(%a1), %0
1960    ldx\t%1, %0
1961    stx\t%r1, %0
1962    fmovd\t%1, %0
1963    ldd\t%1, %0
1964    std\t%1, %0
1965    fzero\t%0"
1966   [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga")
1967    (set_attr "fptype" "*,*,*,*,double,*,*,double")])
1968
1969 (define_expand "movdi_pic_label_ref"
1970   [(set (match_dup 3) (high:DI
1971      (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
1972                  (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1973    (set (match_dup 4) (lo_sum:DI (match_dup 3)
1974      (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1975    (set (match_operand:DI 0 "register_operand" "=r")
1976         (minus:DI (match_dup 5) (match_dup 4)))]
1977   "TARGET_ARCH64 && flag_pic"
1978 {
1979   current_function_uses_pic_offset_table = 1;
1980   operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
1981   if (no_new_pseudos)
1982     {
1983       operands[3] = operands[0];
1984       operands[4] = operands[0];
1985     }
1986   else
1987     {
1988       operands[3] = gen_reg_rtx (DImode);
1989       operands[4] = gen_reg_rtx (DImode);
1990     }
1991   operands[5] = pic_offset_table_rtx;
1992 })
1993
1994 (define_insn "*movdi_high_pic_label_ref"
1995   [(set (match_operand:DI 0 "register_operand" "=r")
1996         (high:DI
1997           (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
1998                       (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1999   "TARGET_ARCH64 && flag_pic"
2000   "sethi\t%%hi(%a2-(%a1-.)), %0")
2001
2002 (define_insn "*movdi_lo_sum_pic_label_ref"
2003   [(set (match_operand:DI 0 "register_operand" "=r")
2004       (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2005         (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2006                     (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2007   "TARGET_ARCH64 && flag_pic"
2008   "or\t%1, %%lo(%a3-(%a2-.)), %0")
2009
2010 ;; SPARC-v9 code model support insns.  See sparc_emit_set_symbolic_const64
2011 ;; in sparc.c to see what is going on here... PIC stuff comes first.
2012
2013 (define_insn "movdi_lo_sum_pic"
2014   [(set (match_operand:DI 0 "register_operand" "=r")
2015         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2016                    (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
2017   "TARGET_ARCH64 && flag_pic"
2018   "or\t%1, %%lo(%a2), %0")
2019
2020 (define_insn "movdi_high_pic"
2021   [(set (match_operand:DI 0 "register_operand" "=r")
2022         (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
2023   "TARGET_ARCH64 && flag_pic && check_pic (1)"
2024   "sethi\t%%hi(%a1), %0")
2025
2026 (define_insn "*sethi_di_medlow_embmedany_pic"
2027   [(set (match_operand:DI 0 "register_operand" "=r")
2028         (high:DI (match_operand:DI 1 "medium_pic_operand" "")))]
2029   "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2030   "sethi\t%%hi(%a1), %0")
2031
2032 (define_insn "*sethi_di_medlow"
2033   [(set (match_operand:DI 0 "register_operand" "=r")
2034         (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2035   "TARGET_CM_MEDLOW && check_pic (1)"
2036   "sethi\t%%hi(%a1), %0")
2037
2038 (define_insn "*losum_di_medlow"
2039   [(set (match_operand:DI 0 "register_operand" "=r")
2040         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2041                    (match_operand:DI 2 "symbolic_operand" "")))]
2042   "TARGET_CM_MEDLOW"
2043   "or\t%1, %%lo(%a2), %0")
2044
2045 (define_insn "seth44"
2046   [(set (match_operand:DI 0 "register_operand" "=r")
2047         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
2048   "TARGET_CM_MEDMID"
2049   "sethi\t%%h44(%a1), %0")
2050
2051 (define_insn "setm44"
2052   [(set (match_operand:DI 0 "register_operand" "=r")
2053         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2054                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
2055   "TARGET_CM_MEDMID"
2056   "or\t%1, %%m44(%a2), %0")
2057
2058 (define_insn "setl44"
2059   [(set (match_operand:DI 0 "register_operand" "=r")
2060         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2061                    (match_operand:DI 2 "symbolic_operand" "")))]
2062   "TARGET_CM_MEDMID"
2063   "or\t%1, %%l44(%a2), %0")
2064
2065 (define_insn "sethh"
2066   [(set (match_operand:DI 0 "register_operand" "=r")
2067         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
2068   "TARGET_CM_MEDANY"
2069   "sethi\t%%hh(%a1), %0")
2070
2071 (define_insn "setlm"
2072   [(set (match_operand:DI 0 "register_operand" "=r")
2073         (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
2074   "TARGET_CM_MEDANY"
2075   "sethi\t%%lm(%a1), %0")
2076
2077 (define_insn "sethm"
2078   [(set (match_operand:DI 0 "register_operand" "=r")
2079         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2080                    (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
2081   "TARGET_CM_MEDANY"
2082   "or\t%1, %%hm(%a2), %0")
2083
2084 (define_insn "setlo"
2085   [(set (match_operand:DI 0 "register_operand" "=r")
2086         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2087                    (match_operand:DI 2 "symbolic_operand" "")))]
2088   "TARGET_CM_MEDANY"
2089   "or\t%1, %%lo(%a2), %0")
2090
2091 (define_insn "embmedany_sethi"
2092   [(set (match_operand:DI 0 "register_operand" "=r")
2093         (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
2094   "TARGET_CM_EMBMEDANY && check_pic (1)"
2095   "sethi\t%%hi(%a1), %0")
2096
2097 (define_insn "embmedany_losum"
2098   [(set (match_operand:DI 0 "register_operand" "=r")
2099         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2100                    (match_operand:DI 2 "data_segment_operand" "")))]
2101   "TARGET_CM_EMBMEDANY"
2102   "add\t%1, %%lo(%a2), %0")
2103
2104 (define_insn "embmedany_brsum"
2105   [(set (match_operand:DI 0 "register_operand" "=r")
2106         (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
2107   "TARGET_CM_EMBMEDANY"
2108   "add\t%1, %_, %0")
2109
2110 (define_insn "embmedany_textuhi"
2111   [(set (match_operand:DI 0 "register_operand" "=r")
2112         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
2113   "TARGET_CM_EMBMEDANY && check_pic (1)"
2114   "sethi\t%%uhi(%a1), %0")
2115
2116 (define_insn "embmedany_texthi"
2117   [(set (match_operand:DI 0 "register_operand" "=r")
2118         (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
2119   "TARGET_CM_EMBMEDANY && check_pic (1)"
2120   "sethi\t%%hi(%a1), %0")
2121
2122 (define_insn "embmedany_textulo"
2123   [(set (match_operand:DI 0 "register_operand" "=r")
2124         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2125                    (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
2126   "TARGET_CM_EMBMEDANY"
2127   "or\t%1, %%ulo(%a2), %0")
2128
2129 (define_insn "embmedany_textlo"
2130   [(set (match_operand:DI 0 "register_operand" "=r")
2131         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2132                    (match_operand:DI 2 "text_segment_operand" "")))]
2133   "TARGET_CM_EMBMEDANY"
2134   "or\t%1, %%lo(%a2), %0")
2135
2136 ;; Now some patterns to help reload out a bit.
2137 (define_expand "reload_indi"
2138   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2139               (match_operand:DI 1 "immediate_operand" "")
2140               (match_operand:TI 2 "register_operand" "=&r")])]
2141   "(TARGET_CM_MEDANY
2142     || TARGET_CM_EMBMEDANY)
2143    && ! flag_pic"
2144 {
2145   sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2146   DONE;
2147 })
2148
2149 (define_expand "reload_outdi"
2150   [(parallel [(match_operand:DI 0 "register_operand" "=r")
2151               (match_operand:DI 1 "immediate_operand" "")
2152               (match_operand:TI 2 "register_operand" "=&r")])]
2153   "(TARGET_CM_MEDANY
2154     || TARGET_CM_EMBMEDANY)
2155    && ! flag_pic"
2156 {
2157   sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2158   DONE;
2159 })
2160
2161 ;; Split up putting CONSTs and REGs into DI regs when !arch64
2162 (define_split
2163   [(set (match_operand:DI 0 "register_operand" "")
2164         (match_operand:DI 1 "const_int_operand" ""))]
2165   "! TARGET_ARCH64 && reload_completed"
2166   [(clobber (const_int 0))]
2167 {
2168 #if HOST_BITS_PER_WIDE_INT == 32
2169   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2170                         (INTVAL (operands[1]) < 0) ?
2171                         constm1_rtx :
2172                         const0_rtx));
2173   emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2174                         operands[1]));
2175 #else
2176   unsigned int low, high;
2177
2178   low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
2179   high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
2180   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
2181
2182   /* Slick... but this trick loses if this subreg constant part
2183      can be done in one insn.  */
2184   if (low == high
2185       && ! SPARC_SETHI32_P (high)
2186       && ! SPARC_SIMM13_P (high))
2187     emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2188                           gen_highpart (SImode, operands[0])));
2189   else
2190     emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
2191 #endif
2192   DONE;
2193 })
2194
2195 (define_split
2196   [(set (match_operand:DI 0 "register_operand" "")
2197         (match_operand:DI 1 "const_double_operand" ""))]
2198   "reload_completed
2199    && (! TARGET_V9
2200        || (! TARGET_ARCH64
2201            && ((GET_CODE (operands[0]) == REG
2202                 && REGNO (operands[0]) < 32)
2203                || (GET_CODE (operands[0]) == SUBREG
2204                    && GET_CODE (SUBREG_REG (operands[0])) == REG
2205                    && REGNO (SUBREG_REG (operands[0])) < 32))))"
2206   [(clobber (const_int 0))]
2207 {
2208   emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2209                         GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2210
2211   /* Slick... but this trick loses if this subreg constant part
2212      can be done in one insn.  */
2213   if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2214       && ! SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
2215       && ! SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1])))
2216     {
2217       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2218                             gen_highpart (SImode, operands[0])));
2219     }
2220   else
2221     {
2222       emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2223                             GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2224     }
2225   DONE;
2226 })
2227
2228 (define_split
2229   [(set (match_operand:DI 0 "register_operand" "")
2230         (match_operand:DI 1 "register_operand" ""))]
2231   "reload_completed
2232    && (! TARGET_V9
2233        || (! TARGET_ARCH64
2234            && ((GET_CODE (operands[0]) == REG
2235                 && REGNO (operands[0]) < 32)
2236                || (GET_CODE (operands[0]) == SUBREG
2237                    && GET_CODE (SUBREG_REG (operands[0])) == REG
2238                    && REGNO (SUBREG_REG (operands[0])) < 32))))"
2239   [(clobber (const_int 0))]
2240 {
2241   rtx set_dest = operands[0];
2242   rtx set_src = operands[1];
2243   rtx dest1, dest2;
2244   rtx src1, src2;
2245
2246   dest1 = gen_highpart (SImode, set_dest);
2247   dest2 = gen_lowpart (SImode, set_dest);
2248   src1 = gen_highpart (SImode, set_src);
2249   src2 = gen_lowpart (SImode, set_src);
2250
2251   /* Now emit using the real source and destination we found, swapping
2252      the order if we detect overlap.  */
2253   if (reg_overlap_mentioned_p (dest1, src2))
2254     {
2255       emit_insn (gen_movsi (dest2, src2));
2256       emit_insn (gen_movsi (dest1, src1));
2257     }
2258   else
2259     {
2260       emit_insn (gen_movsi (dest1, src1));
2261       emit_insn (gen_movsi (dest2, src2));
2262     }
2263   DONE;
2264 })
2265
2266 ;; Now handle the cases of memory moves from/to non-even
2267 ;; DI mode register pairs.
2268 (define_split
2269   [(set (match_operand:DI 0 "register_operand" "")
2270         (match_operand:DI 1 "memory_operand" ""))]
2271   "(! TARGET_ARCH64
2272     && reload_completed
2273     && sparc_splitdi_legitimate (operands[0], operands[1]))"
2274   [(clobber (const_int 0))]
2275 {
2276   rtx word0 = adjust_address (operands[1], SImode, 0);
2277   rtx word1 = adjust_address (operands[1], SImode, 4);
2278   rtx high_part = gen_highpart (SImode, operands[0]);
2279   rtx low_part = gen_lowpart (SImode, operands[0]);
2280
2281   if (reg_overlap_mentioned_p (high_part, word1))
2282     {
2283       emit_insn (gen_movsi (low_part, word1));
2284       emit_insn (gen_movsi (high_part, word0));
2285     }
2286   else
2287     {
2288       emit_insn (gen_movsi (high_part, word0));
2289       emit_insn (gen_movsi (low_part, word1));
2290     }
2291   DONE;
2292 })
2293
2294 (define_split
2295   [(set (match_operand:DI 0 "memory_operand" "")
2296         (match_operand:DI 1 "register_operand" ""))]
2297   "(! TARGET_ARCH64
2298     && reload_completed
2299     && sparc_splitdi_legitimate (operands[1], operands[0]))"
2300   [(clobber (const_int 0))]
2301 {
2302   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
2303                         gen_highpart (SImode, operands[1])));
2304   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
2305                         gen_lowpart (SImode, operands[1])));
2306   DONE;
2307 })
2308
2309 (define_split
2310   [(set (match_operand:DI 0 "memory_operand" "")
2311         (match_operand:DI 1 "const_zero_operand" ""))]
2312   "reload_completed
2313    && (! TARGET_V9
2314        || (! TARGET_ARCH64
2315            && ! mem_min_alignment (operands[0], 8)))
2316    && offsettable_memref_p (operands[0])"
2317   [(clobber (const_int 0))]
2318 {
2319   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
2320   emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
2321   DONE;
2322 })
2323
2324
2325 ;; Floating point and vector move instructions
2326
2327 ;; We don't define V1SI because SI should work just fine.
2328 (define_mode_macro V32 [SF V2HI V4QI])
2329
2330 ;; Yes, you guessed it right, the former movsf expander.
2331 (define_expand "mov<V32:mode>"
2332   [(set (match_operand:V32 0 "nonimmediate_operand" "")
2333         (match_operand:V32 1 "general_operand" ""))]
2334   "<V32:MODE>mode == SFmode || TARGET_VIS"
2335 {
2336   if (sparc_expand_move (<V32:MODE>mode, operands))
2337     DONE;
2338 })
2339
2340 (define_insn "*movsf_insn"
2341   [(set (match_operand:V32 0 "nonimmediate_operand" "=d,f,*r,*r,*r,f,*r,m,m")
2342         (match_operand:V32 1 "input_operand"        "GY,f,*rRY,Q,S,m,m,f,*rGY"))]
2343   "TARGET_FPU
2344    && (register_operand (operands[0], <V32:MODE>mode)
2345        || register_or_zero_operand (operands[1], <V32:MODE>mode))"
2346 {
2347   if (GET_CODE (operands[1]) == CONST_DOUBLE
2348       && (which_alternative == 2
2349           || which_alternative == 3
2350           || which_alternative == 4))
2351     {
2352       REAL_VALUE_TYPE r;
2353       long i;
2354
2355       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2356       REAL_VALUE_TO_TARGET_SINGLE (r, i);
2357       operands[1] = GEN_INT (i);
2358     }
2359
2360   switch (which_alternative)
2361     {
2362     case 0:
2363       return "fzeros\t%0";
2364     case 1:
2365       return "fmovs\t%1, %0";
2366     case 2:
2367       return "mov\t%1, %0";
2368     case 3:
2369       return "sethi\t%%hi(%a1), %0";
2370     case 4:
2371       return "#";
2372     case 5:
2373     case 6:
2374       return "ld\t%1, %0";
2375     case 7:
2376     case 8:
2377       return "st\t%r1, %0";
2378     default:
2379       gcc_unreachable ();
2380     }
2381 }
2382   [(set_attr "type" "fga,fpmove,*,*,*,fpload,load,fpstore,store")])
2383
2384 ;; Exactly the same as above, except that all `f' cases are deleted.
2385 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2386 ;; when -mno-fpu.
2387
2388 (define_insn "*movsf_insn_no_fpu"
2389   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
2390         (match_operand:SF 1 "input_operand"    "rR,Q,S,m,rG"))]
2391   "! TARGET_FPU
2392    && (register_operand (operands[0], SFmode)
2393        || register_or_zero_operand (operands[1], SFmode))"
2394 {
2395   if (GET_CODE (operands[1]) == CONST_DOUBLE
2396       && (which_alternative == 0
2397           || which_alternative == 1
2398           || which_alternative == 2))
2399     {
2400       REAL_VALUE_TYPE r;
2401       long i;
2402
2403       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2404       REAL_VALUE_TO_TARGET_SINGLE (r, i);
2405       operands[1] = GEN_INT (i);
2406     }
2407
2408   switch (which_alternative)
2409     {
2410     case 0:
2411       return "mov\t%1, %0";
2412     case 1:
2413       return "sethi\t%%hi(%a1), %0";
2414     case 2:
2415       return "#";
2416     case 3:
2417       return "ld\t%1, %0";
2418     case 4:
2419       return "st\t%r1, %0";
2420     default:
2421       gcc_unreachable ();
2422     }
2423 }
2424   [(set_attr "type" "*,*,*,load,store")])
2425
2426 ;; The following 3 patterns build SFmode constants in integer registers.
2427
2428 (define_insn "*movsf_lo_sum"
2429   [(set (match_operand:SF 0 "register_operand" "=r")
2430         (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
2431                    (match_operand:SF 2 "fp_const_high_losum_operand" "S")))]
2432   ""
2433 {
2434   REAL_VALUE_TYPE r;
2435   long i;
2436
2437   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
2438   REAL_VALUE_TO_TARGET_SINGLE (r, i);
2439   operands[2] = GEN_INT (i);
2440   return "or\t%1, %%lo(%a2), %0";
2441 })
2442
2443 (define_insn "*movsf_high"
2444   [(set (match_operand:SF 0 "register_operand" "=r")
2445         (high:SF (match_operand:SF 1 "fp_const_high_losum_operand" "S")))]
2446   ""
2447 {
2448   REAL_VALUE_TYPE r;
2449   long i;
2450
2451   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2452   REAL_VALUE_TO_TARGET_SINGLE (r, i);
2453   operands[1] = GEN_INT (i);
2454   return "sethi\t%%hi(%1), %0";
2455 })
2456
2457 (define_split
2458   [(set (match_operand:SF 0 "register_operand" "")
2459         (match_operand:SF 1 "fp_const_high_losum_operand" ""))]
2460   "REG_P (operands[0]) && REGNO (operands[0]) < 32"
2461   [(set (match_dup 0) (high:SF (match_dup 1)))
2462    (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
2463
2464 (define_mode_macro V64 [DF V2SI V4HI V8QI])
2465
2466 ;; Yes, you again guessed it right, the former movdf expander.
2467 (define_expand "mov<V64:mode>"
2468   [(set (match_operand:V64 0 "nonimmediate_operand" "")
2469         (match_operand:V64 1 "general_operand" ""))]
2470   "<V64:MODE>mode == DFmode || TARGET_VIS"
2471 {
2472   if (sparc_expand_move (<V64:MODE>mode, operands))
2473     DONE;
2474 })
2475
2476 ;; Be careful, fmovd does not exist when !v9.
2477 (define_insn "*movdf_insn_sp32"
2478   [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
2479         (match_operand:DF 1 "input_operand"    "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
2480   "TARGET_FPU
2481    && ! TARGET_V9
2482    && (register_operand (operands[0], DFmode)
2483        || register_or_zero_operand (operands[1], DFmode))"
2484   "@
2485   ldd\t%1, %0
2486   std\t%1, %0
2487   ldd\t%1, %0
2488   std\t%1, %0
2489   #
2490   #
2491   #
2492   #
2493   #
2494   #"
2495  [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
2496   (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
2497
2498 (define_insn "*movdf_insn_sp32_no_fpu"
2499   [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
2500         (match_operand:DF 1 "input_operand"    "T,U,G,ro,r"))]
2501   "! TARGET_FPU
2502    && ! TARGET_V9
2503    && (register_operand (operands[0], DFmode)
2504        || register_or_zero_operand (operands[1], DFmode))"
2505   "@
2506   ldd\t%1, %0
2507   std\t%1, %0
2508   #
2509   #
2510   #"
2511   [(set_attr "type" "load,store,*,*,*")
2512    (set_attr "length" "*,*,2,2,2")])
2513
2514 ;; We have available v9 double floats but not 64-bit integer registers.
2515 (define_insn "*movdf_insn_sp32_v9"
2516   [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,T,W,U,T,f,*r,o")
2517         (match_operand:V64 1 "input_operand" "GY,e,W#F,GY,e,T,U,o#F,*roGYF,*rGYf"))]
2518   "TARGET_FPU
2519    && TARGET_V9
2520    && ! TARGET_ARCH64
2521    && (register_operand (operands[0], <V64:MODE>mode)
2522        || register_or_zero_operand (operands[1], <V64:MODE>mode))"
2523   "@
2524   fzero\t%0
2525   fmovd\t%1, %0
2526   ldd\t%1, %0
2527   stx\t%r1, %0
2528   std\t%1, %0
2529   ldd\t%1, %0
2530   std\t%1, %0
2531   #
2532   #
2533   #"
2534   [(set_attr "type" "fga,fpmove,load,store,store,load,store,*,*,*")
2535    (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
2536    (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
2537
2538 (define_insn "*movdf_insn_sp32_v9_no_fpu"
2539   [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
2540         (match_operand:DF 1 "input_operand"    "T,U,G,ro,rG"))]
2541   "! TARGET_FPU
2542    && TARGET_V9
2543    && ! TARGET_ARCH64
2544    && (register_operand (operands[0], DFmode)
2545        || register_or_zero_operand (operands[1], DFmode))"
2546   "@
2547   ldd\t%1, %0
2548   std\t%1, %0
2549   stx\t%r1, %0
2550   #
2551   #"
2552   [(set_attr "type" "load,store,store,*,*")
2553    (set_attr "length" "*,*,*,2,2")])
2554
2555 ;; We have available both v9 double floats and 64-bit integer registers.
2556 (define_insn "*movdf_insn_sp64"
2557   [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,W,*r,*r,m,*r")
2558         (match_operand:V64 1 "input_operand"    "GY,e,W#F,e,*rGY,m,*rGY,F"))]
2559   "TARGET_FPU
2560    && TARGET_ARCH64
2561    && (register_operand (operands[0], <V64:MODE>mode)
2562        || register_or_zero_operand (operands[1], <V64:MODE>mode))"
2563   "@
2564   fzero\t%0
2565   fmovd\t%1, %0
2566   ldd\t%1, %0
2567   std\t%1, %0
2568   mov\t%r1, %0
2569   ldx\t%1, %0
2570   stx\t%r1, %0
2571   #"
2572   [(set_attr "type" "fga,fpmove,load,store,*,load,store,*")
2573    (set_attr "length" "*,*,*,*,*,*,*,2")
2574    (set_attr "fptype" "double,double,*,*,*,*,*,*")])
2575
2576 (define_insn "*movdf_insn_sp64_no_fpu"
2577   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
2578         (match_operand:DF 1 "input_operand"    "r,m,rG"))]
2579   "! TARGET_FPU
2580    && TARGET_ARCH64
2581    && (register_operand (operands[0], DFmode)
2582        || register_or_zero_operand (operands[1], DFmode))"
2583   "@
2584   mov\t%1, %0
2585   ldx\t%1, %0
2586   stx\t%r1, %0"
2587   [(set_attr "type" "*,load,store")])
2588
2589 ;; This pattern build DFmode constants in integer registers.
2590 (define_split
2591   [(set (match_operand:DF 0 "register_operand" "")
2592         (match_operand:DF 1 "const_double_operand" ""))]
2593   "TARGET_FPU
2594    && (GET_CODE (operands[0]) == REG
2595        && REGNO (operands[0]) < 32)
2596    && ! const_zero_operand(operands[1], DFmode)
2597    && reload_completed"
2598   [(clobber (const_int 0))]
2599 {
2600   REAL_VALUE_TYPE r;
2601   long l[2];
2602
2603   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2604   REAL_VALUE_TO_TARGET_DOUBLE (r, l);
2605   operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
2606
2607   if (TARGET_ARCH64)
2608     {
2609 #if HOST_BITS_PER_WIDE_INT == 32
2610       gcc_unreachable ();
2611 #else
2612       HOST_WIDE_INT val;
2613
2614       val = ((HOST_WIDE_INT)(unsigned long)l[1] |
2615              ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
2616       emit_insn (gen_movdi (operands[0], gen_int_mode (val, DImode)));
2617 #endif
2618     }
2619   else
2620     {
2621       emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2622                             gen_int_mode (l[0], SImode)));
2623
2624       /* Slick... but this trick loses if this subreg constant part
2625          can be done in one insn.  */
2626       if (l[1] == l[0]
2627           && ! SPARC_SETHI32_P (l[0])
2628           && ! SPARC_SIMM13_P (l[0]))
2629         {
2630           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2631                                 gen_highpart (SImode, operands[0])));
2632         }
2633       else
2634         {
2635           emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2636                                 gen_int_mode (l[1], SImode)));
2637         }
2638     }
2639   DONE;
2640 })
2641
2642 ;; Ok, now the splits to handle all the multi insn and
2643 ;; mis-aligned memory address cases.
2644 ;; In these splits please take note that we must be
2645 ;; careful when V9 but not ARCH64 because the integer
2646 ;; register DFmode cases must be handled.
2647 (define_split
2648   [(set (match_operand:V64 0 "register_operand" "")
2649         (match_operand:V64 1 "register_operand" ""))]
2650   "(! TARGET_V9
2651     || (! TARGET_ARCH64
2652         && ((GET_CODE (operands[0]) == REG
2653              && REGNO (operands[0]) < 32)
2654             || (GET_CODE (operands[0]) == SUBREG
2655                 && GET_CODE (SUBREG_REG (operands[0])) == REG
2656                 && REGNO (SUBREG_REG (operands[0])) < 32))))
2657    && reload_completed"
2658   [(clobber (const_int 0))]
2659 {
2660   rtx set_dest = operands[0];
2661   rtx set_src = operands[1];
2662   rtx dest1, dest2;
2663   rtx src1, src2;
2664   enum machine_mode half_mode;
2665
2666   /* We can be expanded for DFmode or integral vector modes.  */
2667   if (<V64:MODE>mode == DFmode)
2668     half_mode = SFmode;
2669   else
2670     half_mode = SImode;
2671   
2672   dest1 = gen_highpart (half_mode, set_dest);
2673   dest2 = gen_lowpart (half_mode, set_dest);
2674   src1 = gen_highpart (half_mode, set_src);
2675   src2 = gen_lowpart (half_mode, set_src);
2676
2677   /* Now emit using the real source and destination we found, swapping
2678      the order if we detect overlap.  */
2679   if (reg_overlap_mentioned_p (dest1, src2))
2680     {
2681       emit_move_insn_1 (dest2, src2);
2682       emit_move_insn_1 (dest1, src1);
2683     }
2684   else
2685     {
2686       emit_move_insn_1 (dest1, src1);
2687       emit_move_insn_1 (dest2, src2);
2688     }
2689   DONE;
2690 })
2691
2692 (define_split
2693   [(set (match_operand:V64 0 "register_operand" "")
2694         (match_operand:V64 1 "memory_operand" ""))]
2695   "reload_completed
2696    && ! TARGET_ARCH64
2697    && (((REGNO (operands[0]) % 2) != 0)
2698        || ! mem_min_alignment (operands[1], 8))
2699    && offsettable_memref_p (operands[1])"
2700   [(clobber (const_int 0))]
2701 {
2702   enum machine_mode half_mode;
2703   rtx word0, word1;
2704
2705   /* We can be expanded for DFmode or integral vector modes.  */
2706   if (<V64:MODE>mode == DFmode)
2707     half_mode = SFmode;
2708   else
2709     half_mode = SImode;
2710
2711   word0 = adjust_address (operands[1], half_mode, 0);
2712   word1 = adjust_address (operands[1], half_mode, 4);
2713
2714   if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1))
2715     {
2716       emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
2717       emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
2718     }
2719   else
2720     {
2721       emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
2722       emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
2723     }
2724   DONE;
2725 })
2726
2727 (define_split
2728   [(set (match_operand:V64 0 "memory_operand" "")
2729         (match_operand:V64 1 "register_operand" ""))]
2730   "reload_completed
2731    && ! TARGET_ARCH64
2732    && (((REGNO (operands[1]) % 2) != 0)
2733        || ! mem_min_alignment (operands[0], 8))
2734    && offsettable_memref_p (operands[0])"
2735   [(clobber (const_int 0))]
2736 {
2737   enum machine_mode half_mode;
2738   rtx word0, word1;
2739
2740   /* We can be expanded for DFmode or integral vector modes.  */
2741   if (<V64:MODE>mode == DFmode)
2742     half_mode = SFmode;
2743   else
2744     half_mode = SImode;
2745
2746   word0 = adjust_address (operands[0], half_mode, 0);
2747   word1 = adjust_address (operands[0], half_mode, 4);
2748
2749   emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1]));
2750   emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1]));
2751   DONE;
2752 })
2753
2754 (define_split
2755   [(set (match_operand:V64 0 "memory_operand" "")
2756         (match_operand:V64 1 "const_zero_operand" ""))]
2757   "reload_completed
2758    && (! TARGET_V9
2759        || (! TARGET_ARCH64
2760            && ! mem_min_alignment (operands[0], 8)))
2761    && offsettable_memref_p (operands[0])"
2762   [(clobber (const_int 0))]
2763 {
2764   enum machine_mode half_mode;
2765   rtx dest1, dest2;
2766
2767   /* We can be expanded for DFmode or integral vector modes.  */
2768   if (<V64:MODE>mode == DFmode)
2769     half_mode = SFmode;
2770   else
2771     half_mode = SImode;
2772
2773   dest1 = adjust_address (operands[0], half_mode, 0);
2774   dest2 = adjust_address (operands[0], half_mode, 4);
2775
2776   emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
2777   emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
2778   DONE;
2779 })
2780
2781 (define_split
2782   [(set (match_operand:V64 0 "register_operand" "")
2783         (match_operand:V64 1 "const_zero_operand" ""))]
2784   "reload_completed
2785    && ! TARGET_ARCH64
2786    && ((GET_CODE (operands[0]) == REG
2787         && REGNO (operands[0]) < 32)
2788        || (GET_CODE (operands[0]) == SUBREG
2789            && GET_CODE (SUBREG_REG (operands[0])) == REG
2790            && REGNO (SUBREG_REG (operands[0])) < 32))"
2791   [(clobber (const_int 0))]
2792 {
2793   enum machine_mode half_mode;
2794   rtx set_dest = operands[0];
2795   rtx dest1, dest2;
2796
2797   /* We can be expanded for DFmode or integral vector modes.  */
2798   if (<V64:MODE>mode == DFmode)
2799     half_mode = SFmode;
2800   else
2801     half_mode = SImode;
2802
2803   dest1 = gen_highpart (half_mode, set_dest);
2804   dest2 = gen_lowpart (half_mode, set_dest);
2805   emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
2806   emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
2807   DONE;
2808 })
2809
2810 (define_expand "movtf"
2811   [(set (match_operand:TF 0 "nonimmediate_operand" "")
2812         (match_operand:TF 1 "general_operand" ""))]
2813   ""
2814 {
2815   if (sparc_expand_move (TFmode, operands))
2816     DONE;
2817 })
2818
2819 (define_insn "*movtf_insn_sp32"
2820   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,U,r")
2821         (match_operand:TF 1 "input_operand"    "G,oe,GeUr,o,roG"))]
2822   "TARGET_FPU
2823    && ! TARGET_ARCH64
2824    && (register_operand (operands[0], TFmode)
2825        || register_or_zero_operand (operands[1], TFmode))"
2826   "#"
2827   [(set_attr "length" "4")])
2828
2829 ;; Exactly the same as above, except that all `e' cases are deleted.
2830 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2831 ;; when -mno-fpu.
2832
2833 (define_insn "*movtf_insn_sp32_no_fpu"
2834   [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
2835         (match_operand:TF 1 "input_operand"    "G,o,U,roG,r"))]
2836   "! TARGET_FPU
2837    && ! TARGET_ARCH64
2838    && (register_operand (operands[0], TFmode)
2839        || register_or_zero_operand (operands[1], TFmode))"
2840   "#"
2841   [(set_attr "length" "4")])
2842
2843 (define_insn "*movtf_insn_sp64"
2844   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
2845         (match_operand:TF 1 "input_operand"    "G,oe,Ger,roG"))]
2846   "TARGET_FPU
2847    && TARGET_ARCH64
2848    && ! TARGET_HARD_QUAD
2849    && (register_operand (operands[0], TFmode)
2850        || register_or_zero_operand (operands[1], TFmode))"
2851   "#"
2852   [(set_attr "length" "2")])
2853
2854 (define_insn "*movtf_insn_sp64_hq"
2855   [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
2856         (match_operand:TF 1 "input_operand"    "G,e,m,e,rG,roG"))]
2857   "TARGET_FPU
2858    && TARGET_ARCH64
2859    && TARGET_HARD_QUAD
2860    && (register_operand (operands[0], TFmode)
2861        || register_or_zero_operand (operands[1], TFmode))"
2862   "@
2863   #
2864   fmovq\t%1, %0
2865   ldq\t%1, %0
2866   stq\t%1, %0
2867   #
2868   #"
2869   [(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
2870    (set_attr "length" "2,*,*,*,2,2")])
2871
2872 (define_insn "*movtf_insn_sp64_no_fpu"
2873   [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
2874         (match_operand:TF 1 "input_operand"    "orG,rG"))]
2875   "! TARGET_FPU
2876    && TARGET_ARCH64
2877    && (register_operand (operands[0], TFmode)
2878        || register_or_zero_operand (operands[1], TFmode))"
2879   "#"
2880   [(set_attr "length" "2")])
2881
2882 ;; Now all the splits to handle multi-insn TF mode moves.
2883 (define_split
2884   [(set (match_operand:TF 0 "register_operand" "")
2885         (match_operand:TF 1 "register_operand" ""))]
2886   "reload_completed
2887    && (! TARGET_ARCH64
2888        || (TARGET_FPU
2889            && ! TARGET_HARD_QUAD)
2890        || ! fp_register_operand (operands[0], TFmode))"
2891   [(clobber (const_int 0))]
2892 {
2893   rtx set_dest = operands[0];
2894   rtx set_src = operands[1];
2895   rtx dest1, dest2;
2896   rtx src1, src2;
2897
2898   dest1 = gen_df_reg (set_dest, 0);
2899   dest2 = gen_df_reg (set_dest, 1);
2900   src1 = gen_df_reg (set_src, 0);
2901   src2 = gen_df_reg (set_src, 1);
2902
2903   /* Now emit using the real source and destination we found, swapping
2904      the order if we detect overlap.  */
2905   if (reg_overlap_mentioned_p (dest1, src2))
2906     {
2907       emit_insn (gen_movdf (dest2, src2));
2908       emit_insn (gen_movdf (dest1, src1));
2909     }
2910   else
2911     {
2912       emit_insn (gen_movdf (dest1, src1));
2913       emit_insn (gen_movdf (dest2, src2));
2914     }
2915   DONE;
2916 })
2917
2918 (define_split
2919   [(set (match_operand:TF 0 "nonimmediate_operand" "")
2920         (match_operand:TF 1 "const_zero_operand" ""))]
2921   "reload_completed"
2922   [(clobber (const_int 0))]
2923 {
2924   rtx set_dest = operands[0];
2925   rtx dest1, dest2;
2926
2927   switch (GET_CODE (set_dest))
2928     {
2929     case REG:
2930       dest1 = gen_df_reg (set_dest, 0);
2931       dest2 = gen_df_reg (set_dest, 1);
2932       break;
2933     case MEM:
2934       dest1 = adjust_address (set_dest, DFmode, 0);
2935       dest2 = adjust_address (set_dest, DFmode, 8);
2936       break;
2937     default:
2938       gcc_unreachable ();      
2939     }
2940
2941   emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
2942   emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
2943   DONE;
2944 })
2945
2946 (define_split
2947   [(set (match_operand:TF 0 "register_operand" "")
2948         (match_operand:TF 1 "memory_operand" ""))]
2949   "(reload_completed
2950     && offsettable_memref_p (operands[1])
2951     && (! TARGET_ARCH64
2952         || ! TARGET_HARD_QUAD
2953         || ! fp_register_operand (operands[0], TFmode)))"
2954   [(clobber (const_int 0))]
2955 {
2956   rtx word0 = adjust_address (operands[1], DFmode, 0);
2957   rtx word1 = adjust_address (operands[1], DFmode, 8);
2958   rtx set_dest, dest1, dest2;
2959
2960   set_dest = operands[0];
2961
2962   dest1 = gen_df_reg (set_dest, 0);
2963   dest2 = gen_df_reg (set_dest, 1);
2964
2965   /* Now output, ordering such that we don't clobber any registers
2966      mentioned in the address.  */
2967   if (reg_overlap_mentioned_p (dest1, word1))
2968
2969     {
2970       emit_insn (gen_movdf (dest2, word1));
2971       emit_insn (gen_movdf (dest1, word0));
2972     }
2973   else
2974    {
2975       emit_insn (gen_movdf (dest1, word0));
2976       emit_insn (gen_movdf (dest2, word1));
2977    }
2978   DONE;
2979 })
2980
2981 (define_split
2982   [(set (match_operand:TF 0 "memory_operand" "")
2983         (match_operand:TF 1 "register_operand" ""))]
2984   "(reload_completed
2985     && offsettable_memref_p (operands[0])
2986     && (! TARGET_ARCH64
2987         || ! TARGET_HARD_QUAD
2988         || ! fp_register_operand (operands[1], TFmode)))"
2989   [(clobber (const_int 0))]
2990 {
2991   rtx set_src = operands[1];
2992
2993   emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
2994                         gen_df_reg (set_src, 0)));
2995   emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
2996                         gen_df_reg (set_src, 1)));
2997   DONE;
2998 })
2999
3000
3001 ;; SPARC-V9 conditional move instructions.
3002
3003 ;; We can handle larger constants here for some flavors, but for now we keep
3004 ;; it simple and only allow those constants supported by all flavors.
3005 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3006 ;; 3 contains the constant if one is present, but we handle either for
3007 ;; generality (sparc.c puts a constant in operand 2).
3008
3009 (define_expand "movqicc"
3010   [(set (match_operand:QI 0 "register_operand" "")
3011         (if_then_else:QI (match_operand 1 "comparison_operator" "")
3012                          (match_operand:QI 2 "arith10_operand" "")
3013                          (match_operand:QI 3 "arith10_operand" "")))]
3014   "TARGET_V9"
3015 {
3016   enum rtx_code code = GET_CODE (operands[1]);
3017
3018   if (GET_MODE (sparc_compare_op0) == DImode
3019       && ! TARGET_ARCH64)
3020     FAIL;
3021
3022   if (sparc_compare_op1 == const0_rtx
3023       && GET_CODE (sparc_compare_op0) == REG
3024       && GET_MODE (sparc_compare_op0) == DImode
3025       && v9_regcmp_p (code))
3026     {
3027       operands[1] = gen_rtx_fmt_ee (code, DImode,
3028                              sparc_compare_op0, sparc_compare_op1);
3029     }
3030   else
3031     {
3032       rtx cc_reg = gen_compare_reg (code);
3033       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3034     }
3035 })
3036
3037 (define_expand "movhicc"
3038   [(set (match_operand:HI 0 "register_operand" "")
3039         (if_then_else:HI (match_operand 1 "comparison_operator" "")
3040                          (match_operand:HI 2 "arith10_operand" "")
3041                          (match_operand:HI 3 "arith10_operand" "")))]
3042   "TARGET_V9"
3043 {
3044   enum rtx_code code = GET_CODE (operands[1]);
3045
3046   if (GET_MODE (sparc_compare_op0) == DImode
3047       && ! TARGET_ARCH64)
3048     FAIL;
3049
3050   if (sparc_compare_op1 == const0_rtx
3051       && GET_CODE (sparc_compare_op0) == REG
3052       && GET_MODE (sparc_compare_op0) == DImode
3053       && v9_regcmp_p (code))
3054     {
3055       operands[1] = gen_rtx_fmt_ee (code, DImode,
3056                              sparc_compare_op0, sparc_compare_op1);
3057     }
3058   else
3059     {
3060       rtx cc_reg = gen_compare_reg (code);
3061       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3062     }
3063 })
3064
3065 (define_expand "movsicc"
3066   [(set (match_operand:SI 0 "register_operand" "")
3067         (if_then_else:SI (match_operand 1 "comparison_operator" "")
3068                          (match_operand:SI 2 "arith10_operand" "")
3069                          (match_operand:SI 3 "arith10_operand" "")))]
3070   "TARGET_V9"
3071 {
3072   enum rtx_code code = GET_CODE (operands[1]);
3073   enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3074
3075   if (sparc_compare_op1 == const0_rtx
3076       && GET_CODE (sparc_compare_op0) == REG
3077       && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3078     {
3079       operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3080                              sparc_compare_op0, sparc_compare_op1);
3081     }
3082   else
3083     {
3084       rtx cc_reg = gen_compare_reg (code);
3085       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3086                                     cc_reg, const0_rtx);
3087     }
3088 })
3089
3090 (define_expand "movdicc"
3091   [(set (match_operand:DI 0 "register_operand" "")
3092         (if_then_else:DI (match_operand 1 "comparison_operator" "")
3093                          (match_operand:DI 2 "arith10_operand" "")
3094                          (match_operand:DI 3 "arith10_operand" "")))]
3095   "TARGET_ARCH64"
3096 {
3097   enum rtx_code code = GET_CODE (operands[1]);
3098
3099   if (sparc_compare_op1 == const0_rtx
3100       && GET_CODE (sparc_compare_op0) == REG
3101       && GET_MODE (sparc_compare_op0) == DImode
3102       && v9_regcmp_p (code))
3103     {
3104       operands[1] = gen_rtx_fmt_ee (code, DImode,
3105                              sparc_compare_op0, sparc_compare_op1);
3106     }
3107   else
3108     {
3109       rtx cc_reg = gen_compare_reg (code);
3110       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3111                                     cc_reg, const0_rtx);
3112     }
3113 })
3114
3115 (define_expand "movsfcc"
3116   [(set (match_operand:SF 0 "register_operand" "")
3117         (if_then_else:SF (match_operand 1 "comparison_operator" "")
3118                          (match_operand:SF 2 "register_operand" "")
3119                          (match_operand:SF 3 "register_operand" "")))]
3120   "TARGET_V9 && TARGET_FPU"
3121 {
3122   enum rtx_code code = GET_CODE (operands[1]);
3123
3124   if (GET_MODE (sparc_compare_op0) == DImode
3125       && ! TARGET_ARCH64)
3126     FAIL;
3127
3128   if (sparc_compare_op1 == const0_rtx
3129       && GET_CODE (sparc_compare_op0) == REG
3130       && GET_MODE (sparc_compare_op0) == DImode
3131       && v9_regcmp_p (code))
3132     {
3133       operands[1] = gen_rtx_fmt_ee (code, DImode,
3134                              sparc_compare_op0, sparc_compare_op1);
3135     }
3136   else
3137     {
3138       rtx cc_reg = gen_compare_reg (code);
3139       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3140     }
3141 })
3142
3143 (define_expand "movdfcc"
3144   [(set (match_operand:DF 0 "register_operand" "")
3145         (if_then_else:DF (match_operand 1 "comparison_operator" "")
3146                          (match_operand:DF 2 "register_operand" "")
3147                          (match_operand:DF 3 "register_operand" "")))]
3148   "TARGET_V9 && TARGET_FPU"
3149 {
3150   enum rtx_code code = GET_CODE (operands[1]);
3151
3152   if (GET_MODE (sparc_compare_op0) == DImode
3153       && ! TARGET_ARCH64)
3154     FAIL;
3155
3156   if (sparc_compare_op1 == const0_rtx
3157       && GET_CODE (sparc_compare_op0) == REG
3158       && GET_MODE (sparc_compare_op0) == DImode
3159       && v9_regcmp_p (code))
3160     {
3161       operands[1] = gen_rtx_fmt_ee (code, DImode,
3162                              sparc_compare_op0, sparc_compare_op1);
3163     }
3164   else
3165     {
3166       rtx cc_reg = gen_compare_reg (code);
3167       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3168     }
3169 })
3170
3171 (define_expand "movtfcc"
3172   [(set (match_operand:TF 0 "register_operand" "")
3173         (if_then_else:TF (match_operand 1 "comparison_operator" "")
3174                          (match_operand:TF 2 "register_operand" "")
3175                          (match_operand:TF 3 "register_operand" "")))]
3176   "TARGET_V9 && TARGET_FPU"
3177 {
3178   enum rtx_code code = GET_CODE (operands[1]);
3179
3180   if (GET_MODE (sparc_compare_op0) == DImode
3181       && ! TARGET_ARCH64)
3182     FAIL;
3183
3184   if (sparc_compare_op1 == const0_rtx
3185       && GET_CODE (sparc_compare_op0) == REG
3186       && GET_MODE (sparc_compare_op0) == DImode
3187       && v9_regcmp_p (code))
3188     {
3189       operands[1] = gen_rtx_fmt_ee (code, DImode,
3190                              sparc_compare_op0, sparc_compare_op1);
3191     }
3192   else
3193     {
3194       rtx cc_reg = gen_compare_reg (code);
3195       operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3196     }
3197 })
3198
3199 ;; Conditional move define_insns.
3200
3201 (define_insn "*movqi_cc_sp64"
3202   [(set (match_operand:QI 0 "register_operand" "=r,r")
3203         (if_then_else:QI (match_operator 1 "comparison_operator"
3204                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3205                                  (const_int 0)])
3206                          (match_operand:QI 3 "arith11_operand" "rL,0")
3207                          (match_operand:QI 4 "arith11_operand" "0,rL")))]
3208   "TARGET_V9"
3209   "@
3210    mov%C1\t%x2, %3, %0
3211    mov%c1\t%x2, %4, %0"
3212   [(set_attr "type" "cmove")])
3213
3214 (define_insn "*movhi_cc_sp64"
3215   [(set (match_operand:HI 0 "register_operand" "=r,r")
3216         (if_then_else:HI (match_operator 1 "comparison_operator"
3217                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3218                                  (const_int 0)])
3219                          (match_operand:HI 3 "arith11_operand" "rL,0")
3220                          (match_operand:HI 4 "arith11_operand" "0,rL")))]
3221   "TARGET_V9"
3222   "@
3223    mov%C1\t%x2, %3, %0
3224    mov%c1\t%x2, %4, %0"
3225   [(set_attr "type" "cmove")])
3226
3227 (define_insn "*movsi_cc_sp64"
3228   [(set (match_operand:SI 0 "register_operand" "=r,r")
3229         (if_then_else:SI (match_operator 1 "comparison_operator"
3230                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3231                                  (const_int 0)])
3232                          (match_operand:SI 3 "arith11_operand" "rL,0")
3233                          (match_operand:SI 4 "arith11_operand" "0,rL")))]
3234   "TARGET_V9"
3235   "@
3236    mov%C1\t%x2, %3, %0
3237    mov%c1\t%x2, %4, %0"
3238   [(set_attr "type" "cmove")])
3239
3240 (define_insn "*movdi_cc_sp64"
3241   [(set (match_operand:DI 0 "register_operand" "=r,r")
3242         (if_then_else:DI (match_operator 1 "comparison_operator"
3243                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3244                                  (const_int 0)])
3245                          (match_operand:DI 3 "arith11_operand" "rL,0")
3246                          (match_operand:DI 4 "arith11_operand" "0,rL")))]
3247   "TARGET_ARCH64"
3248   "@
3249    mov%C1\t%x2, %3, %0
3250    mov%c1\t%x2, %4, %0"
3251   [(set_attr "type" "cmove")])
3252
3253 (define_insn "*movdi_cc_sp64_trunc"
3254   [(set (match_operand:SI 0 "register_operand" "=r,r")
3255         (if_then_else:SI (match_operator 1 "comparison_operator"
3256                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3257                                  (const_int 0)])
3258                          (match_operand:SI 3 "arith11_operand" "rL,0")
3259                          (match_operand:SI 4 "arith11_operand" "0,rL")))]
3260   "TARGET_ARCH64"
3261   "@
3262    mov%C1\t%x2, %3, %0
3263    mov%c1\t%x2, %4, %0"
3264   [(set_attr "type" "cmove")])
3265
3266 (define_insn "*movsf_cc_sp64"
3267   [(set (match_operand:SF 0 "register_operand" "=f,f")
3268         (if_then_else:SF (match_operator 1 "comparison_operator"
3269                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3270                                  (const_int 0)])
3271                          (match_operand:SF 3 "register_operand" "f,0")
3272                          (match_operand:SF 4 "register_operand" "0,f")))]
3273   "TARGET_V9 && TARGET_FPU"
3274   "@
3275    fmovs%C1\t%x2, %3, %0
3276    fmovs%c1\t%x2, %4, %0"
3277   [(set_attr "type" "fpcmove")])
3278
3279 (define_insn "movdf_cc_sp64"
3280   [(set (match_operand:DF 0 "register_operand" "=e,e")
3281         (if_then_else:DF (match_operator 1 "comparison_operator"
3282                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3283                                  (const_int 0)])
3284                          (match_operand:DF 3 "register_operand" "e,0")
3285                          (match_operand:DF 4 "register_operand" "0,e")))]
3286   "TARGET_V9 && TARGET_FPU"
3287   "@
3288    fmovd%C1\t%x2, %3, %0
3289    fmovd%c1\t%x2, %4, %0"
3290   [(set_attr "type" "fpcmove")
3291    (set_attr "fptype" "double")])
3292
3293 (define_insn "*movtf_cc_hq_sp64"
3294   [(set (match_operand:TF 0 "register_operand" "=e,e")
3295         (if_then_else:TF (match_operator 1 "comparison_operator"
3296                                 [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3297                                  (const_int 0)])
3298                          (match_operand:TF 3 "register_operand" "e,0")
3299                          (match_operand:TF 4 "register_operand" "0,e")))]
3300   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3301   "@
3302    fmovq%C1\t%x2, %3, %0
3303    fmovq%c1\t%x2, %4, %0"
3304   [(set_attr "type" "fpcmove")])
3305
3306 (define_insn_and_split "*movtf_cc_sp64"
3307   [(set (match_operand:TF 0 "register_operand" "=e,e")
3308         (if_then_else:TF (match_operator 1 "comparison_operator"
3309                             [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
3310                              (const_int 0)])
3311                          (match_operand:TF 3 "register_operand" "e,0")
3312                          (match_operand:TF 4 "register_operand" "0,e")))]
3313   "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
3314   "#"
3315   "&& reload_completed"
3316   [(clobber (const_int 0))]
3317 {
3318   rtx set_dest = operands[0];
3319   rtx set_srca = operands[3];
3320   rtx set_srcb = operands[4];
3321   int third = rtx_equal_p (set_dest, set_srca);
3322   rtx dest1, dest2;
3323   rtx srca1, srca2, srcb1, srcb2;
3324
3325   dest1 = gen_df_reg (set_dest, 0);
3326   dest2 = gen_df_reg (set_dest, 1);
3327   srca1 = gen_df_reg (set_srca, 0);
3328   srca2 = gen_df_reg (set_srca, 1);
3329   srcb1 = gen_df_reg (set_srcb, 0);
3330   srcb2 = gen_df_reg (set_srcb, 1);
3331
3332   /* Now emit using the real source and destination we found, swapping
3333      the order if we detect overlap.  */
3334   if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3335       || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3336     {
3337       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3338       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3339     }
3340   else
3341     {
3342       emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3343       emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3344     }
3345   DONE;
3346 }
3347   [(set_attr "length" "2")])
3348
3349 (define_insn "*movqi_cc_reg_sp64"
3350   [(set (match_operand:QI 0 "register_operand" "=r,r")
3351         (if_then_else:QI (match_operator 1 "v9_register_compare_operator"
3352                                 [(match_operand:DI 2 "register_operand" "r,r")
3353                                  (const_int 0)])
3354                          (match_operand:QI 3 "arith10_operand" "rM,0")
3355                          (match_operand:QI 4 "arith10_operand" "0,rM")))]
3356   "TARGET_ARCH64"
3357   "@
3358    movr%D1\t%2, %r3, %0
3359    movr%d1\t%2, %r4, %0"
3360   [(set_attr "type" "cmove")])
3361
3362 (define_insn "*movhi_cc_reg_sp64"
3363   [(set (match_operand:HI 0 "register_operand" "=r,r")
3364         (if_then_else:HI (match_operator 1 "v9_register_compare_operator"
3365                                 [(match_operand:DI 2 "register_operand" "r,r")
3366                                  (const_int 0)])
3367                          (match_operand:HI 3 "arith10_operand" "rM,0")
3368                          (match_operand:HI 4 "arith10_operand" "0,rM")))]
3369   "TARGET_ARCH64"
3370   "@
3371    movr%D1\t%2, %r3, %0
3372    movr%d1\t%2, %r4, %0"
3373   [(set_attr "type" "cmove")])
3374
3375 (define_insn "*movsi_cc_reg_sp64"
3376   [(set (match_operand:SI 0 "register_operand" "=r,r")
3377         (if_then_else:SI (match_operator 1 "v9_register_compare_operator"
3378                                 [(match_operand:DI 2 "register_operand" "r,r")
3379                                  (const_int 0)])
3380                          (match_operand:SI 3 "arith10_operand" "rM,0")
3381                          (match_operand:SI 4 "arith10_operand" "0,rM")))]
3382   "TARGET_ARCH64"
3383   "@
3384    movr%D1\t%2, %r3, %0
3385    movr%d1\t%2, %r4, %0"
3386   [(set_attr "type" "cmove")])
3387
3388 (define_insn "*movdi_cc_reg_sp64"
3389   [(set (match_operand:DI 0 "register_operand" "=r,r")
3390         (if_then_else:DI (match_operator 1 "v9_register_compare_operator"
3391                                 [(match_operand:DI 2 "register_operand" "r,r")
3392                                  (const_int 0)])
3393                          (match_operand:DI 3 "arith10_operand" "rM,0")
3394                          (match_operand:DI 4 "arith10_operand" "0,rM")))]
3395   "TARGET_ARCH64"
3396   "@
3397    movr%D1\t%2, %r3, %0
3398    movr%d1\t%2, %r4, %0"
3399   [(set_attr "type" "cmove")])
3400
3401 (define_insn "*movsf_cc_reg_sp64"
3402   [(set (match_operand:SF 0 "register_operand" "=f,f")
3403         (if_then_else:SF (match_operator 1 "v9_register_compare_operator"
3404                                 [(match_operand:DI 2 "register_operand" "r,r")
3405                                  (const_int 0)])
3406                          (match_operand:SF 3 "register_operand" "f,0")
3407                          (match_operand:SF 4 "register_operand" "0,f")))]
3408   "TARGET_ARCH64 && TARGET_FPU"
3409   "@
3410    fmovrs%D1\t%2, %3, %0
3411    fmovrs%d1\t%2, %4, %0"
3412   [(set_attr "type" "fpcrmove")])
3413
3414 (define_insn "movdf_cc_reg_sp64"
3415   [(set (match_operand:DF 0 "register_operand" "=e,e")
3416         (if_then_else:DF (match_operator 1 "v9_register_compare_operator"
3417                                 [(match_operand:DI 2 "register_operand" "r,r")
3418                                  (const_int 0)])
3419                          (match_operand:DF 3 "register_operand" "e,0")
3420                          (match_operand:DF 4 "register_operand" "0,e")))]
3421   "TARGET_ARCH64 && TARGET_FPU"
3422   "@
3423    fmovrd%D1\t%2, %3, %0
3424    fmovrd%d1\t%2, %4, %0"
3425   [(set_attr "type" "fpcrmove")
3426    (set_attr "fptype" "double")])
3427
3428 (define_insn "*movtf_cc_reg_hq_sp64"
3429   [(set (match_operand:TF 0 "register_operand" "=e,e")
3430         (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
3431                                 [(match_operand:DI 2 "register_operand" "r,r")
3432                                  (const_int 0)])
3433                          (match_operand:TF 3 "register_operand" "e,0")
3434                          (match_operand:TF 4 "register_operand" "0,e")))]
3435   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3436   "@
3437    fmovrq%D1\t%2, %3, %0
3438    fmovrq%d1\t%2, %4, %0"
3439   [(set_attr "type" "fpcrmove")])
3440
3441 (define_insn_and_split "*movtf_cc_reg_sp64"
3442   [(set (match_operand:TF 0 "register_operand" "=e,e")
3443         (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
3444                                 [(match_operand:DI 2 "register_operand" "r,r")
3445                                  (const_int 0)])
3446                          (match_operand:TF 3 "register_operand" "e,0")
3447                          (match_operand:TF 4 "register_operand" "0,e")))]
3448   "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
3449   "#"
3450   "&& reload_completed"
3451   [(clobber (const_int 0))]
3452 {
3453   rtx set_dest = operands[0];
3454   rtx set_srca = operands[3];
3455   rtx set_srcb = operands[4];
3456   int third = rtx_equal_p (set_dest, set_srca);
3457   rtx dest1, dest2;
3458   rtx srca1, srca2, srcb1, srcb2;
3459
3460   dest1 = gen_df_reg (set_dest, 0);
3461   dest2 = gen_df_reg (set_dest, 1);
3462   srca1 = gen_df_reg (set_srca, 0);
3463   srca2 = gen_df_reg (set_srca, 1);
3464   srcb1 = gen_df_reg (set_srcb, 0);
3465   srcb2 = gen_df_reg (set_srcb, 1);
3466
3467   /* Now emit using the real source and destination we found, swapping
3468      the order if we detect overlap.  */
3469   if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3470       || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3471     {
3472       emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3473       emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3474     }
3475   else
3476     {
3477       emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3478       emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3479     }
3480   DONE;
3481 }
3482   [(set_attr "length" "2")])
3483
3484 \f
3485 ;; Zero-extension instructions
3486
3487 ;; These patterns originally accepted general_operands, however, slightly
3488 ;; better code is generated by only accepting register_operands, and then
3489 ;; letting combine generate the ldu[hb] insns.
3490
3491 (define_expand "zero_extendhisi2"
3492   [(set (match_operand:SI 0 "register_operand" "")
3493         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
3494   ""
3495 {
3496   rtx temp = gen_reg_rtx (SImode);
3497   rtx shift_16 = GEN_INT (16);
3498   int op1_subbyte = 0;
3499
3500   if (GET_CODE (operand1) == SUBREG)
3501     {
3502       op1_subbyte = SUBREG_BYTE (operand1);
3503       op1_subbyte /= GET_MODE_SIZE (SImode);
3504       op1_subbyte *= GET_MODE_SIZE (SImode);
3505       operand1 = XEXP (operand1, 0);
3506     }
3507
3508   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
3509                           shift_16));
3510   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
3511   DONE;
3512 })
3513
3514 (define_insn "*zero_extendhisi2_insn"
3515   [(set (match_operand:SI 0 "register_operand" "=r")
3516         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3517   ""
3518   "lduh\t%1, %0"
3519   [(set_attr "type" "load")
3520    (set_attr "us3load_type" "3cycle")])
3521
3522 (define_expand "zero_extendqihi2"
3523   [(set (match_operand:HI 0 "register_operand" "")
3524         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
3525   ""
3526   "")
3527
3528 (define_insn "*zero_extendqihi2_insn"
3529   [(set (match_operand:HI 0 "register_operand" "=r,r")
3530         (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
3531   "GET_CODE (operands[1]) != CONST_INT"
3532   "@
3533    and\t%1, 0xff, %0
3534    ldub\t%1, %0"
3535   [(set_attr "type" "*,load")
3536    (set_attr "us3load_type" "*,3cycle")])
3537
3538 (define_expand "zero_extendqisi2"
3539   [(set (match_operand:SI 0 "register_operand" "")
3540         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
3541   ""
3542   "")
3543
3544 (define_insn "*zero_extendqisi2_insn"
3545   [(set (match_operand:SI 0 "register_operand" "=r,r")
3546         (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
3547   "GET_CODE (operands[1]) != CONST_INT"
3548   "@
3549    and\t%1, 0xff, %0
3550    ldub\t%1, %0"
3551   [(set_attr "type" "*,load")
3552    (set_attr "us3load_type" "*,3cycle")])
3553
3554 (define_expand "zero_extendqidi2"
3555   [(set (match_operand:DI 0 "register_operand" "")
3556         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
3557   "TARGET_ARCH64"
3558   "")
3559
3560 (define_insn "*zero_extendqidi2_insn"
3561   [(set (match_operand:DI 0 "register_operand" "=r,r")
3562         (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
3563   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
3564   "@
3565    and\t%1, 0xff, %0
3566    ldub\t%1, %0"
3567   [(set_attr "type" "*,load")
3568    (set_attr "us3load_type" "*,3cycle")])
3569
3570 (define_expand "zero_extendhidi2"
3571   [(set (match_operand:DI 0 "register_operand" "")
3572         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
3573   "TARGET_ARCH64"
3574 {
3575   rtx temp = gen_reg_rtx (DImode);
3576   rtx shift_48 = GEN_INT (48);
3577   int op1_subbyte = 0;
3578
3579   if (GET_CODE (operand1) == SUBREG)
3580     {
3581       op1_subbyte = SUBREG_BYTE (operand1);
3582       op1_subbyte /= GET_MODE_SIZE (DImode);
3583       op1_subbyte *= GET_MODE_SIZE (DImode);
3584       operand1 = XEXP (operand1, 0);
3585     }
3586
3587   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
3588                           shift_48));
3589   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
3590   DONE;
3591 })
3592
3593 (define_insn "*zero_extendhidi2_insn"
3594   [(set (match_operand:DI 0 "register_operand" "=r")
3595         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3596   "TARGET_ARCH64"
3597   "lduh\t%1, %0"
3598   [(set_attr "type" "load")
3599    (set_attr "us3load_type" "3cycle")])
3600
3601 ;; ??? Write truncdisi pattern using sra?
3602
3603 (define_expand "zero_extendsidi2"
3604   [(set (match_operand:DI 0 "register_operand" "")
3605         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
3606   ""
3607   "")
3608
3609 (define_insn "*zero_extendsidi2_insn_sp64"
3610   [(set (match_operand:DI 0 "register_operand" "=r,r")
3611         (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
3612   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
3613   "@
3614    srl\t%1, 0, %0
3615    lduw\t%1, %0"
3616   [(set_attr "type" "shift,load")])
3617
3618 (define_insn_and_split "*zero_extendsidi2_insn_sp32"
3619   [(set (match_operand:DI 0 "register_operand" "=r")
3620         (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
3621   "! TARGET_ARCH64"
3622   "#"
3623   "&& reload_completed"
3624   [(set (match_dup 2) (match_dup 3))
3625    (set (match_dup 4) (match_dup 5))]
3626 {
3627   rtx dest1, dest2;
3628
3629   dest1 = gen_highpart (SImode, operands[0]);
3630   dest2 = gen_lowpart (SImode, operands[0]);
3631
3632   /* Swap the order in case of overlap.  */
3633   if (REGNO (dest1) == REGNO (operands[1]))
3634     {
3635       operands[2] = dest2;
3636       operands[3] = operands[1];
3637       operands[4] = dest1;
3638       operands[5] = const0_rtx;
3639     }
3640   else
3641     {
3642       operands[2] = dest1;
3643       operands[3] = const0_rtx;
3644       operands[4] = dest2;
3645       operands[5] = operands[1];
3646     }
3647 }
3648   [(set_attr "length" "2")])
3649
3650 ;; Simplify comparisons of extended values.
3651
3652 (define_insn "*cmp_zero_extendqisi2"
3653   [(set (reg:CC 100)
3654         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
3655                     (const_int 0)))]
3656   ""
3657   "andcc\t%0, 0xff, %%g0"
3658   [(set_attr "type" "compare")])
3659
3660 (define_insn "*cmp_zero_qi"
3661   [(set (reg:CC 100)
3662         (compare:CC (match_operand:QI 0 "register_operand" "r")
3663                     (const_int 0)))]
3664   ""
3665   "andcc\t%0, 0xff, %%g0"
3666   [(set_attr "type" "compare")])
3667
3668 (define_insn "*cmp_zero_extendqisi2_set"
3669   [(set (reg:CC 100)
3670         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
3671                     (const_int 0)))
3672    (set (match_operand:SI 0 "register_operand" "=r")
3673         (zero_extend:SI (match_dup 1)))]
3674   ""
3675   "andcc\t%1, 0xff, %0"
3676   [(set_attr "type" "compare")])
3677
3678 (define_insn "*cmp_zero_extendqisi2_andcc_set"
3679   [(set (reg:CC 100)
3680         (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
3681                             (const_int 255))
3682                     (const_int 0)))
3683    (set (match_operand:SI 0 "register_operand" "=r")
3684         (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
3685   ""
3686   "andcc\t%1, 0xff, %0"
3687   [(set_attr "type" "compare")])
3688
3689 (define_insn "*cmp_zero_extendqidi2"
3690   [(set (reg:CCX 100)
3691         (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
3692                      (const_int 0)))]
3693   "TARGET_ARCH64"
3694   "andcc\t%0, 0xff, %%g0"
3695   [(set_attr "type" "compare")])
3696
3697 (define_insn "*cmp_zero_qi_sp64"
3698   [(set (reg:CCX 100)
3699         (compare:CCX (match_operand:QI 0 "register_operand" "r")
3700                      (const_int 0)))]
3701   "TARGET_ARCH64"
3702   "andcc\t%0, 0xff, %%g0"
3703   [(set_attr "type" "compare")])
3704
3705 (define_insn "*cmp_zero_extendqidi2_set"
3706   [(set (reg:CCX 100)
3707         (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
3708                      (const_int 0)))
3709    (set (match_operand:DI 0 "register_operand" "=r")
3710         (zero_extend:DI (match_dup 1)))]
3711   "TARGET_ARCH64"
3712   "andcc\t%1, 0xff, %0"
3713   [(set_attr "type" "compare")])
3714
3715 (define_insn "*cmp_zero_extendqidi2_andcc_set"
3716   [(set (reg:CCX 100)
3717         (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
3718                              (const_int 255))
3719                      (const_int 0)))
3720    (set (match_operand:DI 0 "register_operand" "=r")
3721         (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
3722   "TARGET_ARCH64"
3723   "andcc\t%1, 0xff, %0"
3724   [(set_attr "type" "compare")])
3725
3726 ;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
3727
3728 (define_insn "*cmp_siqi_trunc"
3729   [(set (reg:CC 100)
3730         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
3731                     (const_int 0)))]
3732   ""
3733   "andcc\t%0, 0xff, %%g0"
3734   [(set_attr "type" "compare")])
3735
3736 (define_insn "*cmp_siqi_trunc_set"
3737   [(set (reg:CC 100)
3738         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
3739                     (const_int 0)))
3740    (set (match_operand:QI 0 "register_operand" "=r")
3741         (subreg:QI (match_dup 1) 3))]
3742   ""
3743   "andcc\t%1, 0xff, %0"
3744   [(set_attr "type" "compare")])
3745
3746 (define_insn "*cmp_diqi_trunc"
3747   [(set (reg:CC 100)
3748         (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
3749                     (const_int 0)))]
3750   "TARGET_ARCH64"
3751   "andcc\t%0, 0xff, %%g0"
3752   [(set_attr "type" "compare")])
3753
3754 (define_insn "*cmp_diqi_trunc_set"
3755   [(set (reg:CC 100)
3756         (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
3757                     (const_int 0)))
3758    (set (match_operand:QI 0 "register_operand" "=r")
3759         (subreg:QI (match_dup 1) 7))]
3760   "TARGET_ARCH64"
3761   "andcc\t%1, 0xff, %0"
3762   [(set_attr "type" "compare")])
3763 \f
3764
3765 ;; Sign-extension instructions
3766
3767 ;; These patterns originally accepted general_operands, however, slightly
3768 ;; better code is generated by only accepting register_operands, and then
3769 ;; letting combine generate the lds[hb] insns.
3770
3771 (define_expand "extendhisi2"
3772   [(set (match_operand:SI 0 "register_operand" "")
3773         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
3774   ""
3775 {
3776   rtx temp = gen_reg_rtx (SImode);
3777   rtx shift_16 = GEN_INT (16);
3778   int op1_subbyte = 0;
3779
3780   if (GET_CODE (operand1) == SUBREG)
3781     {
3782       op1_subbyte = SUBREG_BYTE (operand1);
3783       op1_subbyte /= GET_MODE_SIZE (SImode);
3784       op1_subbyte *= GET_MODE_SIZE (SImode);
3785       operand1 = XEXP (operand1, 0);
3786     }
3787
3788   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
3789                           shift_16));
3790   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
3791   DONE;
3792 })
3793
3794 (define_insn "*sign_extendhisi2_insn"
3795   [(set (match_operand:SI 0 "register_operand" "=r")
3796         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3797   ""
3798   "ldsh\t%1, %0"
3799   [(set_attr "type" "sload")
3800    (set_attr "us3load_type" "3cycle")])
3801
3802 (define_expand "extendqihi2"
3803   [(set (match_operand:HI 0 "register_operand" "")
3804         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
3805   ""
3806 {
3807   rtx temp = gen_reg_rtx (SImode);
3808   rtx shift_24 = GEN_INT (24);
3809   int op1_subbyte = 0;
3810   int op0_subbyte = 0;
3811
3812   if (GET_CODE (operand1) == SUBREG)
3813     {
3814       op1_subbyte = SUBREG_BYTE (operand1);
3815       op1_subbyte /= GET_MODE_SIZE (SImode);
3816       op1_subbyte *= GET_MODE_SIZE (SImode);
3817       operand1 = XEXP (operand1, 0);
3818     }
3819   if (GET_CODE (operand0) == SUBREG)
3820     {
3821       op0_subbyte = SUBREG_BYTE (operand0);
3822       op0_subbyte /= GET_MODE_SIZE (SImode);
3823       op0_subbyte *= GET_MODE_SIZE (SImode);
3824       operand0 = XEXP (operand0, 0);
3825     }
3826   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
3827                           shift_24));
3828   if (GET_MODE (operand0) != SImode)
3829     operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
3830   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3831   DONE;
3832 })
3833
3834 (define_insn "*sign_extendqihi2_insn"
3835   [(set (match_operand:HI 0 "register_operand" "=r")
3836         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3837   ""
3838   "ldsb\t%1, %0"
3839   [(set_attr "type" "sload")
3840    (set_attr "us3load_type" "3cycle")])
3841
3842 (define_expand "extendqisi2"
3843   [(set (match_operand:SI 0 "register_operand" "")
3844         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
3845   ""
3846 {
3847   rtx temp = gen_reg_rtx (SImode);
3848   rtx shift_24 = GEN_INT (24);
3849   int op1_subbyte = 0;
3850
3851   if (GET_CODE (operand1) == SUBREG)
3852     {
3853       op1_subbyte = SUBREG_BYTE (operand1);
3854       op1_subbyte /= GET_MODE_SIZE (SImode);
3855       op1_subbyte *= GET_MODE_SIZE (SImode);
3856       operand1 = XEXP (operand1, 0);
3857     }
3858
3859   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
3860                           shift_24));
3861   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3862   DONE;
3863 })
3864
3865 (define_insn "*sign_extendqisi2_insn"
3866   [(set (match_operand:SI 0 "register_operand" "=r")
3867         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3868   ""
3869   "ldsb\t%1, %0"
3870   [(set_attr "type" "sload")
3871    (set_attr "us3load_type" "3cycle")])
3872
3873 (define_expand "extendqidi2"
3874   [(set (match_operand:DI 0 "register_operand" "")
3875         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
3876   "TARGET_ARCH64"
3877 {
3878   rtx temp = gen_reg_rtx (DImode);
3879   rtx shift_56 = GEN_INT (56);
3880   int op1_subbyte = 0;
3881
3882   if (GET_CODE (operand1) == SUBREG)
3883     {
3884       op1_subbyte = SUBREG_BYTE (operand1);
3885       op1_subbyte /= GET_MODE_SIZE (DImode);
3886       op1_subbyte *= GET_MODE_SIZE (DImode);
3887       operand1 = XEXP (operand1, 0);
3888     }
3889
3890   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
3891                           shift_56));
3892   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
3893   DONE;
3894 })
3895
3896 (define_insn "*sign_extendqidi2_insn"
3897   [(set (match_operand:DI 0 "register_operand" "=r")
3898         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
3899   "TARGET_ARCH64"
3900   "ldsb\t%1, %0"
3901   [(set_attr "type" "sload")
3902    (set_attr "us3load_type" "3cycle")])
3903
3904 (define_expand "extendhidi2"
3905   [(set (match_operand:DI 0 "register_operand" "")
3906         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
3907   "TARGET_ARCH64"
3908 {
3909   rtx temp = gen_reg_rtx (DImode);
3910   rtx shift_48 = GEN_INT (48);
3911   int op1_subbyte = 0;
3912
3913   if (GET_CODE (operand1) == SUBREG)
3914     {
3915       op1_subbyte = SUBREG_BYTE (operand1);
3916       op1_subbyte /= GET_MODE_SIZE (DImode);
3917       op1_subbyte *= GET_MODE_SIZE (DImode);
3918       operand1 = XEXP (operand1, 0);
3919     }
3920
3921   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
3922                           shift_48));
3923   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
3924   DONE;
3925 })
3926
3927 (define_insn "*sign_extendhidi2_insn"
3928   [(set (match_operand:DI 0 "register_operand" "=r")
3929         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3930   "TARGET_ARCH64"
3931   "ldsh\t%1, %0"
3932   [(set_attr "type" "sload")
3933    (set_attr "us3load_type" "3cycle")])
3934
3935 (define_expand "extendsidi2"
3936   [(set (match_operand:DI 0 "register_operand" "")
3937         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
3938   "TARGET_ARCH64"
3939   "")
3940
3941 (define_insn "*sign_extendsidi2_insn"
3942   [(set (match_operand:DI 0 "register_operand" "=r,r")
3943         (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
3944   "TARGET_ARCH64"
3945   "@
3946   sra\t%1, 0, %0
3947   ldsw\t%1, %0"
3948   [(set_attr "type" "shift,sload")
3949    (set_attr "us3load_type" "*,3cycle")])
3950
3951
3952 ;; Special pattern for optimizing bit-field compares.  This is needed
3953 ;; because combine uses this as a canonical form.
3954
3955 (define_insn "*cmp_zero_extract"
3956   [(set (reg:CC 100)
3957         (compare:CC
3958          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
3959                           (match_operand:SI 1 "small_int_operand" "I")
3960                           (match_operand:SI 2 "small_int_operand" "I"))
3961          (const_int 0)))]
3962   "INTVAL (operands[2]) > 19"
3963 {
3964   int len = INTVAL (operands[1]);
3965   int pos = 32 - INTVAL (operands[2]) - len;
3966   HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
3967   operands[1] = GEN_INT (mask);
3968   return "andcc\t%0, %1, %%g0";
3969 }
3970   [(set_attr "type" "compare")])
3971
3972 (define_insn "*cmp_zero_extract_sp64"
3973   [(set (reg:CCX 100)
3974         (compare:CCX
3975          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
3976                           (match_operand:SI 1 "small_int_operand" "I")
3977                           (match_operand:SI 2 "small_int_operand" "I"))
3978          (const_int 0)))]
3979   "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
3980 {
3981   int len = INTVAL (operands[1]);
3982   int pos = 64 - INTVAL (operands[2]) - len;
3983   HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
3984   operands[1] = GEN_INT (mask);
3985   return "andcc\t%0, %1, %%g0";
3986 }
3987   [(set_attr "type" "compare")])
3988
3989
3990 ;; Conversions between float, double and long double.
3991
3992 (define_insn "extendsfdf2"
3993   [(set (match_operand:DF 0 "register_operand" "=e")
3994         (float_extend:DF
3995          (match_operand:SF 1 "register_operand" "f")))]
3996   "TARGET_FPU"
3997   "fstod\t%1, %0"
3998   [(set_attr "type" "fp")
3999    (set_attr "fptype" "double")])
4000
4001 (define_expand "extendsftf2"
4002   [(set (match_operand:TF 0 "nonimmediate_operand" "")
4003         (float_extend:TF
4004          (match_operand:SF 1 "register_operand" "")))]