OSDN Git Service

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