OSDN Git Service

(muldf+1, muldf+2): Add patterns for fsmuld and fdmulq.
[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 Free Software Foundation, Inc.
3 ;;   Contributed by Michael Tiemann (tiemann@cygnus.com)
4
5 ;; This file is part of GNU CC.
6
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; any later version.
11
12 ;; GNU CC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU CC; see the file COPYING.  If not, write to
19 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23
24 ;; Insn type.  Used to default other attribute values.
25
26 ;; type "unary" insns have one input operand (1) and one output operand (0)
27 ;; type "binary" insns have two input operands (1,2) and one output (0)
28 ;; type "compare" insns have one or two input operands (0,1) and no output
29 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
30
31 (define_attr "type"
32   "move,unary,binary,compare,load,store,uncond_branch,branch,call,call_no_delay_slot,address,fpload,fpstore,fp,fpcmp,fpmul,fpdiv,fpsqrt,multi,misc"
33   (const_string "binary"))
34
35 ;; Set true if insn uses call-clobbered intermediate register.
36 (define_attr "use_clobbered" "false,true"
37   (if_then_else (and (eq_attr "type" "address")
38                      (match_operand 0 "clobbered_register" ""))
39                 (const_string "true")
40                 (const_string "false")))
41
42 ;; Length (in # of insns).
43 (define_attr "length" ""
44   (cond [(eq_attr "type" "load,fpload")
45          (if_then_else (match_operand 1 "symbolic_memory_operand" "")
46                        (const_int 2) (const_int 1))
47
48          (eq_attr "type" "store,fpstore")
49          (if_then_else (match_operand 0 "symbolic_memory_operand" "")
50                        (const_int 2) (const_int 1))
51
52          (eq_attr "type" "address") (const_int 2)
53
54          (eq_attr "type" "binary")
55          (if_then_else (ior (match_operand 2 "arith_operand" "")
56                             (match_operand 2 "arith_double_operand" ""))
57                        (const_int 1) (const_int 3))
58
59          (eq_attr "type" "multi") (const_int 2)
60
61          (eq_attr "type" "move,unary")
62          (if_then_else (ior (match_operand 1 "arith_operand" "")
63                             (match_operand 1 "arith_double_operand" ""))
64                        (const_int 1) (const_int 2))]
65
66         (const_int 1)))
67
68 (define_asm_attributes
69   [(set_attr "length" "1")
70    (set_attr "type" "multi")])
71
72 ;; Attributes for instruction and branch scheduling
73
74 (define_attr "in_call_delay" "false,true"
75   (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
76                 (const_string "false")
77          (eq_attr "type" "load,fpload,store,fpstore")
78                 (if_then_else (eq_attr "length" "1")
79                               (const_string "true")
80                               (const_string "false"))
81          (eq_attr "type" "address")
82                 (if_then_else (eq_attr "use_clobbered" "false")
83                               (const_string "true")
84                               (const_string "false"))]
85         (if_then_else (eq_attr "length" "1")
86                       (const_string "true")
87                       (const_string "false"))))
88
89 (define_delay (eq_attr "type" "call")
90   [(eq_attr "in_call_delay" "true") (nil) (nil)])
91
92 ;; ??? Should implement the notion of predelay slots for floating point
93 ;; branches.  This would allow us to remove the nop always inserted before
94 ;; a floating point branch.
95
96 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
97 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
98 ;; This is because doing so will add several pipeline stalls to the path
99 ;; that the load/store did not come from.  Unfortunately, there is no way
100 ;; to prevent fill_eager_delay_slots from using load/store without completely
101 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
102 ;; because it prevents us from moving back the final store of inner loops.
103
104 (define_attr "in_branch_delay" "false,true"
105   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
106                      (eq_attr "length" "1"))
107                 (const_string "true")
108                 (const_string "false")))
109
110 (define_attr "in_uncond_branch_delay" "false,true"
111   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
112                      (eq_attr "length" "1"))
113                 (const_string "true")
114                 (const_string "false")))
115
116 (define_attr "in_annul_branch_delay" "false,true"
117   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
118                      (eq_attr "length" "1"))
119                 (const_string "true")
120                 (const_string "false")))
121
122 (define_delay (eq_attr "type" "branch")
123   [(eq_attr "in_branch_delay" "true")
124    (nil) (eq_attr "in_annul_branch_delay" "true")])
125
126 (define_delay (eq_attr "type" "uncond_branch")
127   [(eq_attr "in_uncond_branch_delay" "true")
128    (nil) (nil)])
129    
130 ;; Function units of the SPARC
131
132 ;; (define_function_unit {name} {num-units} {n-users} {test}
133 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
134
135 ;; The integer ALU.
136 ;; (Noted only for documentation; units that take one cycle do not need to
137 ;; be specified.)
138
139 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
140 ;; the inputs.
141
142 ;; (define_function_unit "alu" 1 0
143 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
144
145 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
146 (define_function_unit "memory" 1 1 (eq_attr "type" "load,fpload") 2 0)
147
148 ;; SPARC has two floating-point units: the FP ALU,
149 ;; and the FP MUL/DIV/SQRT unit.
150 ;; Instruction timings on the CY7C602 are as follows
151 ;; FABSs        4
152 ;; FADDs/d      5/5
153 ;; FCMPs/d      4/4
154 ;; FDIVs/d      23/37
155 ;; FMOVs        4
156 ;; FMULs/d      5/7
157 ;; FNEGs        4
158 ;; FSQRTs/d     34/63
159 ;; FSUBs/d      5/5
160 ;; FdTOi/s      5/5
161 ;; FsTOi/d      5/5
162 ;; FiTOs/d      9/5
163
164 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
165 ;; More insns cause the chip to stall.
166
167 (define_function_unit "fp_alu" 1 1 (eq_attr "type" "fp") 5 0)
168 (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpmul") 7 0)
169 (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpdiv") 37 0)
170 (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpsqrt") 63 0)
171 \f
172 ;; Compare instructions.
173 ;; This controls RTL generation and register allocation.
174
175 ;; We generate RTL for comparisons and branches by having the cmpxx 
176 ;; patterns store away the operands.  Then, the scc and bcc patterns
177 ;; emit RTL for both the compare and the branch.
178 ;;
179 ;; We do this because we want to generate different code for an sne and
180 ;; seq insn.  In those cases, if the second operand of the compare is not
181 ;; const0_rtx, we want to compute the xor of the two operands and test
182 ;; it against zero.
183 ;;
184 ;; We start with the DEFINE_EXPANDs, then then DEFINE_INSNs to match
185 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
186 ;; insns that actually require more than one machine instruction.
187
188 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
189
190 (define_expand "cmpsi"
191   [(set (reg:CC 0)
192         (compare:CC (match_operand:SI 0 "register_operand" "")
193                     (match_operand:SI 1 "arith_operand" "")))]
194   ""
195   "
196 {
197   sparc_compare_op0 = operands[0];
198   sparc_compare_op1 = operands[1];
199   DONE;
200 }")
201
202 (define_expand "cmpsf"
203   [(set (reg:CCFP 0)
204         (compare:CCFP (match_operand:SF 0 "register_operand" "")
205                       (match_operand:SF 1 "register_operand" "")))]
206   "TARGET_FPU"
207   "
208 {
209   sparc_compare_op0 = operands[0];
210   sparc_compare_op1 = operands[1];
211   DONE;
212 }")
213
214 (define_expand "cmpdf"
215   [(set (reg:CCFP 0)
216         (compare:CCFP (match_operand:DF 0 "register_operand" "")
217                       (match_operand:DF 1 "register_operand" "")))]
218   "TARGET_FPU"
219   "
220 {
221   sparc_compare_op0 = operands[0];
222   sparc_compare_op1 = operands[1];
223   DONE;
224 }")
225
226 (define_expand "cmptf"
227   [(set (reg:CCFP 0)
228         (compare:CCFP (match_operand:TF 0 "register_operand" "")
229                       (match_operand:TF 1 "register_operand" "")))]
230   "TARGET_FPU"
231   "
232 {
233   sparc_compare_op0 = operands[0];
234   sparc_compare_op1 = operands[1];
235   DONE;
236 }")
237
238 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
239 ;; without jumps using the addx/subx instructions.  For the rest, we do
240 ;; branches.  Seq_special and sne_special clobber the CC reg, because they
241 ;; generate addcc/subcc instructions.
242
243 (define_expand "seq_special"
244   [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
245                               (match_operand:SI 2 "register_operand" "")))
246    (parallel [(set (match_operand:SI 0 "register_operand" "")
247                    (eq:SI (match_dup 3) (const_int 0)))
248               (clobber (reg:CC 0))])]
249              
250   ""
251   "{ operands[3] = gen_reg_rtx (SImode); }")
252
253 (define_expand "sne_special"
254   [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
255                               (match_operand:SI 2 "register_operand" "")))
256    (parallel [(set (match_operand:SI 0 "register_operand" "")
257                    (ne:SI (match_dup 3) (const_int 0)))
258               (clobber (reg:CC 0))])]
259   ""
260   "{ operands[3] = gen_reg_rtx (SImode); }")
261
262 (define_expand "seq"
263   [(set (match_operand:SI 0 "register_operand" "")
264         (eq:SI (match_dup 1) (const_int 0)))]
265   ""
266   "
267 { if (GET_MODE (sparc_compare_op0) == SImode)
268     {
269       emit_insn (gen_seq_special (operands[0], sparc_compare_op0,
270                                   sparc_compare_op1));
271       DONE;
272     }
273   else
274     operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
275 }")
276
277 (define_expand "sne"
278   [(set (match_operand:SI 0 "register_operand" "")
279         (ne:SI (match_dup 1) (const_int 0)))]
280   ""
281   "
282 { if (GET_MODE (sparc_compare_op0) == SImode)
283     {
284       emit_insn (gen_sne_special (operands[0], sparc_compare_op0,
285                                   sparc_compare_op1));
286       DONE;
287     }
288   else
289     operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
290 }")
291
292 (define_expand "sgt"
293   [(set (match_operand:SI 0 "register_operand" "")
294         (gt:SI (match_dup 1) (const_int 0)))]
295   ""
296   "
297 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
298
299 (define_expand "slt"
300   [(set (match_operand:SI 0 "register_operand" "")
301         (lt:SI (match_dup 1) (const_int 0)))]
302   ""
303   "
304 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
305
306 (define_expand "sge"
307   [(set (match_operand:SI 0 "register_operand" "")
308         (ge:SI (match_dup 1) (const_int 0)))]
309   ""
310   "
311 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
312
313 (define_expand "sle"
314   [(set (match_operand:SI 0 "register_operand" "")
315         (le:SI (match_dup 1) (const_int 0)))]
316   ""
317   "
318 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
319
320 (define_expand "sgtu"
321   [(set (match_operand:SI 0 "register_operand" "")
322         (gtu:SI (match_dup 1) (const_int 0)))]
323   ""
324   "
325 {
326   rtx tem;
327
328   /* We can do ltu easily, so if both operands are registers, swap them and
329      do a LTU.  */
330   if ((GET_CODE (sparc_compare_op0) == REG
331        || GET_CODE (sparc_compare_op0) == SUBREG)
332       && (GET_CODE (sparc_compare_op1) == REG
333           || GET_CODE (sparc_compare_op1) == SUBREG))
334     {
335       tem = sparc_compare_op0;
336       sparc_compare_op0 = sparc_compare_op1;
337       sparc_compare_op1 = tem;
338       emit_insn (gen_sltu (operands[0]));
339       DONE;
340     }
341
342   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
343 }")
344
345 (define_expand "sltu"
346   [(set (match_operand:SI 0 "register_operand" "")
347         (ltu:SI (match_dup 1) (const_int 0)))]
348   ""
349   "
350 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
351 }")
352
353 (define_expand "sgeu"
354   [(set (match_operand:SI 0 "register_operand" "")
355         (geu:SI (match_dup 1) (const_int 0)))]
356   ""
357   "
358 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
359 }")
360
361 (define_expand "sleu"
362   [(set (match_operand:SI 0 "register_operand" "")
363         (leu:SI (match_dup 1) (const_int 0)))]
364   ""
365   "
366 {
367   rtx tem;
368
369   /* We can do geu easily, so if both operands are registers, swap them and
370      do a GEU.  */
371   if ((GET_CODE (sparc_compare_op0) == REG
372        || GET_CODE (sparc_compare_op0) == SUBREG)
373       && (GET_CODE (sparc_compare_op1) == REG
374           || GET_CODE (sparc_compare_op1) == SUBREG))
375     {
376       tem = sparc_compare_op0;
377       sparc_compare_op0 = sparc_compare_op1;
378       sparc_compare_op1 = tem;
379       emit_insn (gen_sgeu (operands[0]));
380       DONE;
381     }
382
383   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
384 }")
385
386 ;; Now the DEFINE_INSNs for the compare and scc cases.  First the compares.
387
388 (define_insn ""
389   [(set (reg:CC 0)
390         (compare:CC (match_operand:SI 0 "register_operand" "r")
391                     (match_operand:SI 1 "arith_operand" "rI")))]
392   ""
393   "cmp %r0,%1"
394   [(set_attr "type" "compare")])
395
396 (define_insn ""
397   [(set (reg:CCFPE 0)
398         (compare:CCFPE (match_operand:DF 0 "register_operand" "f")
399                        (match_operand:DF 1 "register_operand" "f")))]
400   "TARGET_FPU"
401   "fcmped %0,%1"
402   [(set_attr "type" "fpcmp")])
403
404 (define_insn ""
405   [(set (reg:CCFPE 0)
406         (compare:CCFPE (match_operand:SF 0 "register_operand" "f")
407                        (match_operand:SF 1 "register_operand" "f")))]
408   "TARGET_FPU"
409   "fcmpes %0,%1"
410   [(set_attr "type" "fpcmp")])
411
412 (define_insn ""
413   [(set (reg:CCFPE 0)
414         (compare:CCFPE (match_operand:TF 0 "register_operand" "f")
415                        (match_operand:TF 1 "register_operand" "f")))]
416   "TARGET_FPU"
417   "fcmpeq %0,%1"
418   [(set_attr "type" "fpcmp")])
419
420 (define_insn ""
421   [(set (reg:CCFP 0)
422         (compare:CCFP (match_operand:DF 0 "register_operand" "f")
423                       (match_operand:DF 1 "register_operand" "f")))]
424   "TARGET_FPU"
425   "fcmpd %0,%1"
426   [(set_attr "type" "fpcmp")])
427
428 (define_insn ""
429   [(set (reg:CCFP 0)
430         (compare:CCFP (match_operand:SF 0 "register_operand" "f")
431                       (match_operand:SF 1 "register_operand" "f")))]
432   "TARGET_FPU"
433   "fcmps %0,%1"
434   [(set_attr "type" "fpcmp")])
435
436 (define_insn ""
437   [(set (reg:CCFP 0)
438         (compare:CCFP (match_operand:TF 0 "register_operand" "f")
439                       (match_operand:TF 1 "register_operand" "f")))]
440   "TARGET_FPU"
441   "fcmpq %0,%1"
442   [(set_attr "type" "fpcmp")])
443
444 ;; The SEQ and SNE patterns are special because they can be done
445 ;; without any branching and do not involve a COMPARE.
446
447 (define_insn ""
448   [(set (match_operand:SI 0 "register_operand" "=r")
449         (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
450    (clobber (reg:CC 0))]
451   ""
452   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
453   [(set_attr "type" "unary")
454    (set_attr "length" "2")])
455
456 (define_insn ""
457   [(set (match_operand:SI 0 "register_operand" "=r")
458         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
459                        (const_int 0))))
460    (clobber (reg:CC 0))]
461   ""
462   "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
463   [(set_attr "type" "unary")
464    (set_attr "length" "2")])
465
466 (define_insn ""
467   [(set (match_operand:SI 0 "register_operand" "=r")
468         (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
469    (clobber (reg:CC 0))]
470   ""
471   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
472   [(set_attr "type" "unary")
473    (set_attr "length" "2")])
474
475 (define_insn ""
476   [(set (match_operand:SI 0 "register_operand" "=r")
477         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
478                        (const_int 0))))
479    (clobber (reg:CC 0))]
480   ""
481   "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
482   [(set_attr "type" "unary")
483    (set_attr "length" "2")])
484
485 ;; We can also do (x + (i == 0)) and related, so put them in.
486
487 (define_insn ""
488   [(set (match_operand:SI 0 "register_operand" "=r")
489         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
490                         (const_int 0))
491                  (match_operand:SI 2 "register_operand" "r")))
492    (clobber (reg:CC 0))]
493   ""
494   "subcc %%g0,%1,%%g0\;addx %2,0,%0"
495   [(set_attr "length" "2")])
496
497 (define_insn ""
498   [(set (match_operand:SI 0 "register_operand" "=r")
499         (minus:SI (match_operand:SI 2 "register_operand" "r")
500                   (ne:SI (match_operand:SI 1 "register_operand" "r")
501                          (const_int 0))))
502    (clobber (reg:CC 0))]
503   ""
504   "subcc %%g0,%1,%%g0\;subx %2,0,%0"
505   [(set_attr "length" "2")])
506
507 (define_insn ""
508   [(set (match_operand:SI 0 "register_operand" "=r")
509         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
510                         (const_int 0))
511                  (match_operand:SI 2 "register_operand" "r")))
512    (clobber (reg:CC 0))]
513   ""
514   "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
515   [(set_attr "length" "2")])
516
517 (define_insn ""
518   [(set (match_operand:SI 0 "register_operand" "=r")
519         (minus:SI (match_operand:SI 2 "register_operand" "r")
520                   (eq:SI (match_operand:SI 1 "register_operand" "r")
521                          (const_int 0))))
522    (clobber (reg:CC 0))]
523   ""
524   "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
525   [(set_attr "length" "2")])
526
527 ;; We can also do GEU and LTU directly, but these operate after a
528 ;; compare.
529
530 (define_insn ""
531   [(set (match_operand:SI 0 "register_operand" "=r")
532         (ltu:SI (reg:CC 0) (const_int 0)))]
533   ""
534   "addx %%g0,0,%0"
535   [(set_attr "type" "misc")])
536
537 (define_insn ""
538   [(set (match_operand:SI 0 "register_operand" "=r")
539         (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
540   ""
541   "subx %%g0,0,%0"
542   [(set_attr "type" "misc")])
543
544 ;; ??? Combine should canonicalize these next two to the same pattern.
545 (define_insn ""
546   [(set (match_operand:SI 0 "register_operand" "=r")
547         (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0)))
548                   (match_operand:SI 1 "arith_operand" "rI")))]
549   ""
550   "subx %%g0,%1,%0"
551   [(set_attr "type" "unary")])
552
553 (define_insn ""
554   [(set (match_operand:SI 0 "register_operand" "=r")
555         (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
556                          (match_operand:SI 1 "arith_operand" "rI"))))]
557   ""
558   "subx %%g0,%1,%0"
559   [(set_attr "type" "unary")])
560
561 (define_insn ""
562   [(set (match_operand:SI 0 "register_operand" "=r")
563         (geu:SI (reg:CC 0) (const_int 0)))]
564   ""
565   "subx %%g0,-1,%0"
566   [(set_attr "type" "misc")])
567
568 (define_insn ""
569   [(set (match_operand:SI 0 "register_operand" "=r")
570         (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
571   ""
572   "addx %%g0,-1,%0"
573   [(set_attr "type" "misc")])
574
575 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
576
577 (define_insn ""
578   [(set (match_operand:SI 0 "register_operand" "=r")
579         (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
580                  (match_operand:SI 1 "arith_operand" "rI")))]
581   ""
582   "addx %%g0,%1,%0"
583   [(set_attr "type" "unary")])
584
585 (define_insn ""
586   [(set (match_operand:SI 0 "register_operand" "=r")
587         (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
588                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
589                           (match_operand:SI 2 "arith_operand" "rI"))))]
590   ""
591   "addx %1,%2,%0")
592
593 (define_insn ""
594   [(set (match_operand:SI 0 "register_operand" "=r")
595         (minus:SI (match_operand:SI 1 "register_operand" "r")
596                   (ltu:SI (reg:CC 0) (const_int 0))))]
597   ""
598   "subx %1,0,%0"
599   [(set_attr "type" "unary")])
600
601 ;; ??? Combine should canonicalize these next two to the same pattern.
602 (define_insn ""
603   [(set (match_operand:SI 0 "register_operand" "=r")
604         (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
605                             (match_operand:SI 2 "arith_operand" "rI"))
606                   (ltu:SI (reg:CC 0) (const_int 0))))]
607   ""
608   "subx %1,%2,%0")
609
610 (define_insn ""
611   [(set (match_operand:SI 0 "register_operand" "=r")
612         (minus:SI (match_operand:SI 1 "register_operand" "r")
613                   (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
614                            (match_operand:SI 2 "arith_operand" "rI"))))]
615   ""
616   "subx %1,%2,%0")
617
618 (define_insn ""
619   [(set (match_operand:SI 0 "register_operand" "=r")
620         (plus:SI (geu:SI (reg:CC 0) (const_int 0))
621                  (match_operand:SI 1 "register_operand" "r")))]
622   ""
623   "subx %1,-1,%0"
624   [(set_attr "type" "unary")])
625
626 (define_insn ""
627   [(set (match_operand:SI 0 "register_operand" "=r")
628         (minus:SI (match_operand:SI 1 "register_operand" "r")
629                   (geu:SI (reg:CC 0) (const_int 0))))]
630   ""
631   "addx %1,-1,%0"
632   [(set_attr "type" "unary")])
633
634 ;; Now we have the generic scc insns.  These will be done using a jump.
635 ;; We have to exclude the cases above, since we will not want combine to
636 ;; turn something that does not require a jump into something that does.
637 (define_insn ""
638   [(set (match_operand:SI 0 "register_operand" "=r")
639         (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))]
640   ""
641   "* return output_scc_insn (operands, insn); "
642   [(set_attr "type" "multi")
643    (set_attr "length" "3")])
644 \f
645 ;; These control RTL generation for conditional jump insns
646
647 (define_expand "beq"
648   [(set (pc)
649         (if_then_else (eq (match_dup 1) (const_int 0))
650                       (label_ref (match_operand 0 "" ""))
651                       (pc)))]
652   ""
653   "
654 { operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); }")
655
656 (define_expand "bne"
657   [(set (pc)
658         (if_then_else (ne (match_dup 1) (const_int 0))
659                       (label_ref (match_operand 0 "" ""))
660                       (pc)))]
661   ""
662   "
663 { operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); }")
664
665 (define_expand "bgt"
666   [(set (pc)
667         (if_then_else (gt (match_dup 1) (const_int 0))
668                       (label_ref (match_operand 0 "" ""))
669                       (pc)))]
670   ""
671   "
672 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
673
674 (define_expand "bgtu"
675   [(set (pc)
676         (if_then_else (gtu (match_dup 1) (const_int 0))
677                       (label_ref (match_operand 0 "" ""))
678                       (pc)))]
679   ""
680   "
681 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
682 }")
683
684 (define_expand "blt"
685   [(set (pc)
686         (if_then_else (lt (match_dup 1) (const_int 0))
687                       (label_ref (match_operand 0 "" ""))
688                       (pc)))]
689   ""
690   "
691 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
692
693 (define_expand "bltu"
694   [(set (pc)
695         (if_then_else (ltu (match_dup 1) (const_int 0))
696                       (label_ref (match_operand 0 "" ""))
697                       (pc)))]
698   ""
699   "
700 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
701 }")
702
703 (define_expand "bge"
704   [(set (pc)
705         (if_then_else (ge (match_dup 1) (const_int 0))
706                       (label_ref (match_operand 0 "" ""))
707                       (pc)))]
708   ""
709   "
710 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
711
712 (define_expand "bgeu"
713   [(set (pc)
714         (if_then_else (geu (match_dup 1) (const_int 0))
715                       (label_ref (match_operand 0 "" ""))
716                       (pc)))]
717   ""
718   "
719 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
720 }")
721
722 (define_expand "ble"
723   [(set (pc)
724         (if_then_else (le (match_dup 1) (const_int 0))
725                       (label_ref (match_operand 0 "" ""))
726                       (pc)))]
727   ""
728   "
729 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
730
731 (define_expand "bleu"
732   [(set (pc)
733         (if_then_else (leu (match_dup 1) (const_int 0))
734                       (label_ref (match_operand 0 "" ""))
735                       (pc)))]
736   ""
737   "
738 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
739 }")
740 \f
741 ;; Now match both normal and inverted jump.
742
743 (define_insn ""
744   [(set (pc)
745         (if_then_else (match_operator 0 "noov_compare_op"
746                                       [(reg 0) (const_int 0)])
747                       (label_ref (match_operand 1 "" ""))
748                       (pc)))]
749   ""
750   "*
751 {
752   return output_cbranch (operands[0], 1, 0,
753                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
754                          ! final_sequence);
755 }"
756   [(set_attr "type" "branch")])
757
758 (define_insn ""
759   [(set (pc)
760         (if_then_else (match_operator 0 "noov_compare_op"
761                                       [(reg 0) (const_int 0)])
762                       (pc)
763                       (label_ref (match_operand 1 "" ""))))]
764   ""
765   "*
766 {
767   return output_cbranch (operands[0], 1, 1,
768                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
769                          ! final_sequence);
770 }"
771   [(set_attr "type" "branch")])
772 \f
773 ;; Move instructions
774
775 (define_expand "movsi"
776   [(set (match_operand:SI 0 "general_operand" "")
777         (match_operand:SI 1 "general_operand" ""))]
778   ""
779   "
780 {
781   if (emit_move_sequence (operands, SImode, 0))
782     DONE;
783 }")
784
785 (define_expand "reload_insi"
786   [(set (match_operand:SI 0 "register_operand" "=r")
787         (match_operand:SI 1 "general_operand" ""))
788    (clobber (match_operand:SI 2 "register_operand" "=&r"))]
789   ""
790   "
791 {
792   if (emit_move_sequence (operands, SImode, operands[2]))
793     DONE;
794
795   /* We don't want the clobber emitted, so handle this ourselves.  */
796   emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
797   DONE;
798 }")
799
800 ;; We must support both 'r' and 'f' registers here, because combine may
801 ;; convert SFmode hard registers to SImode hard registers when simplifying
802 ;; subreg sets.
803
804 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
805 ;; problems with register allocation.  Reload might try to put an integer
806 ;; in an fp register, or an fp number is an integer register.
807
808 (define_insn ""
809   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,Q,Q,rf")
810         (match_operand:SI 1 "move_operand" "rI,K,Q,!Q,rJ,!f,!fr"))]
811   "register_operand (operands[0], SImode)
812    || register_operand (operands[1], SImode)
813    || operands[1] == const0_rtx"
814   "@
815    mov %1,%0
816    sethi %%hi(%a1),%0
817    ld %1,%0
818    ld %1,%0
819    st %r1,%0
820    st %r1,%0
821    st %r1,[%@-4]\;ld [%@-4],%0"
822   [(set_attr "type" "move,move,load,load,store,store,multi")
823    (set_attr "length" "*,1,*,*,*,*,*")])
824
825 ;; Special pic pattern, for loading the address of a label into a register.
826 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
827 ;; there.
828
829 (define_insn ""
830   [(set (match_operand:SI 0 "register_operand" "=r")
831         (match_operand:SI 1 "move_pic_label" "i"))
832    (set (reg:SI 15) (pc))]
833   ""
834   "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
835   [(set_attr "type" "multi")
836    (set_attr "length" "4")])
837
838 (define_insn ""
839   [(set (match_operand:DI 0 "register_operand" "=r")
840         (high:DI (match_operand 1 "" "")))]
841   "check_pic (1)"
842   "*
843 {
844   rtx op0 = operands[0];
845   rtx op1 = operands[1];
846
847   if (GET_CODE (op1) == CONST_INT)
848     {
849       operands[0] = operand_subword (op0, 1, 0, DImode);
850       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
851
852       operands[0] = operand_subword (op0, 0, 0, DImode);
853       if (INTVAL (op1) < 0)
854         output_asm_insn (\"mov -1,%0\", operands);
855       else
856         output_asm_insn (\"mov 0,%0\", operands);
857     }
858   else if (GET_CODE (op1) == CONST_DOUBLE)
859     {
860       operands[0] = operand_subword (op0, 1, 0, DImode);
861       operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
862       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
863
864       operands[0] = operand_subword (op0, 0, 0, DImode);
865       operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
866       output_asm_insn (singlemove_string (operands), operands);
867     }
868   else
869     abort ();
870 }"
871   [(set_attr "type" "move")
872    (set_attr "length" "2")])
873
874 ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
875 ;; confuse them with real addresses.
876 (define_insn ""
877   [(set (match_operand:SI 0 "register_operand" "=r")
878         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
879   "check_pic (1)"
880   "sethi %%hi(%a1),%0"
881   [(set_attr "type" "move")
882    (set_attr "length" "1")])
883
884 (define_insn ""
885   [(set (match_operand:SI 0 "register_operand" "=r")
886         (high:SI (match_operand 1 "" "")))]
887   "check_pic (1)"
888   "sethi %%hi(%a1),%0"
889   [(set_attr "type" "move")
890    (set_attr "length" "1")])
891
892 (define_insn ""
893   [(set (match_operand:HI 0 "register_operand" "=r")
894         (high:HI (match_operand 1 "" "")))]
895   "check_pic (1)"
896   "sethi %%hi(%a1),%0"
897   [(set_attr "type" "move")
898    (set_attr "length" "1")])
899
900 (define_insn ""
901   [(set (match_operand:DI 0 "register_operand" "=r")
902         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
903                    (match_operand:DI 2 "immediate_operand" "in")))]
904   ""
905   "*
906 {
907   /* Don't output a 64 bit constant, since we can't trust the assembler to
908      handle it correctly.  */
909   if (GET_CODE (operands[2]) == CONST_DOUBLE)
910     operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
911   return \"or %R1,%%lo(%a2),%R0\";
912 }"
913   ;; Need to set length for this arith insn because operand2
914   ;; is not an "arith_operand".
915   [(set_attr "length" "1")])
916
917 ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
918 ;; confuse them with real addresses.
919 (define_insn ""
920   [(set (match_operand:SI 0 "register_operand" "=r")
921         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
922                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
923   ""
924   "or %1,%%lo(%a2),%0"
925   ;; Need to set length for this arith insn because operand2
926   ;; is not an "arith_operand".
927   [(set_attr "length" "1")])
928
929 (define_insn ""
930   [(set (match_operand:SI 0 "register_operand" "=r")
931         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
932                    (match_operand:SI 2 "immediate_operand" "in")))]
933   ""
934   "or %1,%%lo(%a2),%0"
935   ;; Need to set length for this arith insn because operand2
936   ;; is not an "arith_operand".
937   [(set_attr "length" "1")])
938
939 (define_insn ""
940   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
941         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
942    (clobber (match_scratch:SI 2 "=&r"))]
943   ""
944   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
945   [(set_attr "type" "store")
946    (set_attr "length" "2")])
947
948 (define_expand "movhi"
949   [(set (match_operand:HI 0 "general_operand" "")
950         (match_operand:HI 1 "general_operand" ""))]
951   ""
952   "
953 {
954   if (emit_move_sequence (operands, HImode, 0))
955     DONE;
956 }")
957
958 (define_insn ""
959   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
960         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
961   "register_operand (operands[0], HImode)
962    || register_operand (operands[1], HImode)
963    || operands[1] == const0_rtx"
964   "@
965    mov %1,%0
966    sethi %%hi(%a1),%0
967    lduh %1,%0
968    sth %r1,%0"
969   [(set_attr "type" "move,move,load,store")
970    (set_attr "length" "*,1,*,1")])
971
972 (define_insn ""
973   [(set (match_operand:HI 0 "register_operand" "=r")
974         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
975                    (match_operand 2 "immediate_operand" "in")))]
976   ""
977   "or %1,%%lo(%a2),%0"
978   [(set_attr "length" "1")])
979
980 (define_insn ""
981   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
982         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
983    (clobber (match_scratch:SI 2 "=&r"))]
984   ""
985   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
986   [(set_attr "type" "store")
987    (set_attr "length" "2")])
988
989 (define_expand "movqi"
990   [(set (match_operand:QI 0 "general_operand" "")
991         (match_operand:QI 1 "general_operand" ""))]
992   ""
993   "
994 {
995   if (emit_move_sequence (operands, QImode, 0))
996     DONE;
997 }")
998
999 (define_insn ""
1000   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1001         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1002   "register_operand (operands[0], QImode)
1003    || register_operand (operands[1], QImode)
1004    || operands[1] == const0_rtx"
1005   "@
1006    mov %1,%0
1007    sethi %%hi(%a1),%0
1008    ldub %1,%0
1009    stb %r1,%0"
1010   [(set_attr "type" "move,move,load,store")
1011    (set_attr "length" "*,1,*,1")])
1012
1013 (define_insn ""
1014   [(set (match_operand:QI 0 "register_operand" "=r")
1015         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1016                               (match_operand 2 "immediate_operand" "in")) 0))]
1017   ""
1018   "or %1,%%lo(%a2),%0"
1019   [(set_attr "length" "1")])
1020
1021 (define_insn ""
1022   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1023         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1024    (clobber (match_scratch:SI 2 "=&r"))]
1025   ""
1026   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1027   [(set_attr "type" "store")
1028    (set_attr "length" "2")])
1029
1030 ;; The definition of this insn does not really explain what it does,
1031 ;; but it should suffice
1032 ;; that anything generated as this insn will be recognized as one
1033 ;; and that it will not successfully combine with anything.
1034 (define_expand "movstrsi"
1035   [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
1036                    (mem:BLK (match_operand:BLK 1 "general_operand" "")))
1037               (use (match_operand:SI 2 "nonmemory_operand" ""))
1038               (use (match_operand:SI 3 "immediate_operand" ""))
1039               (clobber (match_dup 0))
1040               (clobber (match_dup 1))
1041               (clobber (match_scratch:SI 4 ""))
1042               (clobber (reg:SI 0))
1043               (clobber (reg:SI 1))])]
1044   ""
1045   "
1046 {
1047   /* If the size isn't known, don't emit inline code.  output_block_move
1048      would output code that's much slower than the library function.
1049      Also don't output code for large blocks.  */
1050   if (GET_CODE (operands[2]) != CONST_INT
1051       || GET_CODE (operands[3]) != CONST_INT
1052       || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
1053     FAIL;
1054
1055   operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1056   operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1057   operands[2] = force_not_mem (operands[2]);
1058 }")
1059
1060 (define_insn ""
1061   [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
1062         (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
1063    (use (match_operand:SI 2 "nonmemory_operand" "rn"))
1064    (use (match_operand:SI 3 "immediate_operand" "i"))
1065    (clobber (match_dup 0))
1066    (clobber (match_dup 1))
1067    (clobber (match_scratch:SI 4 "=&r"))
1068    (clobber (reg:SI 0))
1069    (clobber (reg:SI 1))]
1070   ""
1071   "* return output_block_move (operands);"
1072   [(set_attr "type" "multi")
1073    (set_attr "length" "6")])
1074 \f
1075 ;; Floating point move insns
1076
1077 ;; This pattern forces (set (reg:TF ...) (const_double ...))
1078 ;; to be reloaded by putting the constant into memory.
1079 ;; It must come before the more general movtf pattern.
1080 (define_insn ""
1081   [(set (match_operand:TF 0 "general_operand" "=?r,f,o")
1082         (match_operand:TF 1 "" "?E,m,G"))]
1083   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1084   "*
1085 {
1086   switch (which_alternative)
1087     {
1088     case 0:
1089       return output_move_quad (operands);
1090     case 1:
1091       return output_fp_move_quad (operands);
1092     case 2:
1093       operands[1] = adj_offsettable_operand (operands[0], 4);
1094       operands[2] = adj_offsettable_operand (operands[0], 8);
1095       operands[3] = adj_offsettable_operand (operands[0], 12);
1096       return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
1097     }
1098 }"
1099   [(set_attr "type" "load,fpload,store")
1100    (set_attr "length" "5,5,5")])
1101
1102 (define_expand "movtf"
1103   [(set (match_operand:TF 0 "general_operand" "")
1104         (match_operand:TF 1 "general_operand" ""))]
1105   ""
1106   "
1107 {
1108   if (emit_move_sequence (operands, TFmode, 0))
1109     DONE;
1110 }")
1111
1112 (define_insn ""
1113   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r,?f,?r")
1114         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q,r,f"))]
1115   "TARGET_FPU
1116    && (register_operand (operands[0], TFmode)
1117        || register_operand (operands[1], TFmode))"
1118   "*
1119 {
1120   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1121     return output_fp_move_quad (operands);
1122   return output_move_quad (operands);
1123 }"
1124   [(set_attr "type" "fp,move,fpstore,store,fpload,load,multi,multi")
1125    (set_attr "length" "4,4,5,5,5,5,5,5")])
1126
1127 ;; Exactly the same as above, except that all `f' cases are deleted.
1128 ;; This is necessary to prevent reload from ever trying to use a `f' reg
1129 ;; when -mno-fpu.
1130
1131 (define_insn ""
1132   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
1133         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
1134   "! TARGET_FPU
1135    && (register_operand (operands[0], TFmode)
1136        || register_operand (operands[1], TFmode))"
1137   "*
1138 {
1139   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1140     return output_fp_move_quad (operands);
1141   return output_move_quad (operands);
1142 }"
1143   [(set_attr "type" "move,store,load")
1144    (set_attr "length" "4,5,5")])
1145
1146 (define_insn ""
1147   [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
1148         (match_operand:TF 1 "reg_or_0_operand" "rf,G"))
1149    (clobber (match_scratch:SI 2 "=&r,&r"))]
1150   ""
1151   "*
1152 {
1153   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1154   if (which_alternative == 0)
1155     return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
1156   else
1157     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
1158 }"
1159   [(set_attr "type" "store")
1160    (set_attr "length" "5")])
1161 \f
1162 ;; This pattern forces (set (reg:DF ...) (const_double ...))
1163 ;; to be reloaded by putting the constant into memory.
1164 ;; It must come before the more general movdf pattern.
1165
1166 (define_insn ""
1167   [(set (match_operand:DF 0 "general_operand" "=?r,f,o")
1168         (match_operand:DF 1 "" "?E,m,G"))]
1169   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1170   "*
1171 {
1172   switch (which_alternative)
1173     {
1174     case 0:
1175       return output_move_double (operands);
1176     case 1:
1177       return output_fp_move_double (operands);
1178     case 2:
1179       operands[1] = adj_offsettable_operand (operands[0], 4);
1180       return \"st %%g0,%0\;st %%g0,%1\";
1181     }
1182 }"
1183   [(set_attr "type" "load,fpload,store")
1184    (set_attr "length" "3,3,3")])
1185
1186 (define_expand "movdf"
1187   [(set (match_operand:DF 0 "general_operand" "")
1188         (match_operand:DF 1 "general_operand" ""))]
1189   ""
1190   "
1191 {
1192   if (emit_move_sequence (operands, DFmode, 0))
1193     DONE;
1194 }")
1195
1196 (define_insn ""
1197   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,&r,?f,?r")
1198         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q,r,f"))]
1199   "TARGET_FPU
1200    && (register_operand (operands[0], DFmode)
1201        || register_operand (operands[1], DFmode))"
1202   "*
1203 {
1204   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1205     return output_fp_move_double (operands);
1206   return output_move_double (operands);
1207 }"
1208   [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load,multi,multi")
1209    (set_attr "length" "1,1,2,2,3,3,3,3,3,3")])
1210
1211 ;; Exactly the same as above, except that all `f' cases are deleted.
1212 ;; This is necessary to prevent reload from ever trying to use a `f' reg
1213 ;; when -mno-fpu.
1214
1215 (define_insn ""
1216   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
1217         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
1218   "! TARGET_FPU
1219    && (register_operand (operands[0], DFmode)
1220        || register_operand (operands[1], DFmode))"
1221   "* return output_move_double (operands);"
1222   [(set_attr "type" "store,load,move,store,load")
1223    (set_attr "length" "1,1,2,3,3")])
1224
1225 (define_insn ""
1226   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
1227         (match_operand:DF 1 "reg_or_0_operand" "rf,G"))
1228    (clobber (match_scratch:SI 2 "=&r,&r"))]
1229   ""
1230   "*
1231 {
1232   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1233   if (which_alternative == 0)
1234     return \"std %1,[%2+%%lo(%a0)]\";
1235   else
1236     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
1237 }"
1238   [(set_attr "type" "store")
1239    (set_attr "length" "3")])
1240 \f
1241 ;; Double-word move insns.
1242
1243 (define_expand "movdi"
1244   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1245         (match_operand:DI 1 "general_operand" ""))]
1246   ""
1247   "
1248 {
1249   if (emit_move_sequence (operands, DImode, 0))
1250     DONE;
1251 }")
1252
1253 (define_insn ""
1254   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?f,?r,?Q")
1255         (match_operand:DI 1 "general_operand" "r,r,Q,i,r,f,Q,f,f"))]
1256   "register_operand (operands[0], DImode)
1257    || register_operand (operands[1], DImode)
1258    || operands[1] == const0_rtx"
1259   "*
1260 {
1261   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1262     return output_fp_move_double (operands);
1263   return output_move_double (operands);
1264 }"
1265   [(set_attr "type" "move,store,load,multi,multi,fp,fpload,multi,fpstore")
1266    (set_attr "length" "2,3,3,3,3,2,3,3,3")])
1267
1268 ;; Floating-point move insns.
1269
1270 ;; This pattern forces (set (reg:SF ...) (const_double ...))
1271 ;; to be reloaded by putting the constant into memory.
1272 ;; It must come before the more general movsf pattern.
1273 (define_insn ""
1274   [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
1275         (match_operand:SF 1 "" "?E,m,G"))]
1276   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1277   "*
1278 {
1279   switch (which_alternative)
1280     {
1281     case 0:
1282       return singlemove_string (operands);
1283     case 1:
1284       return \"ld %1,%0\";
1285     case 2:
1286       return \"st %%g0,%0\";
1287     }
1288 }"
1289   [(set_attr "type" "load,fpload,store")
1290    (set_attr "length" "2,1,1")])
1291
1292 (define_expand "movsf"
1293   [(set (match_operand:SF 0 "general_operand" "")
1294         (match_operand:SF 1 "general_operand" ""))]
1295   ""
1296   "
1297 {
1298   if (emit_move_sequence (operands, SFmode, 0))
1299     DONE;
1300 }")
1301
1302 (define_insn ""
1303   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,rf,f,r,Q,Q")
1304         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,!rf,Q,Q,f,r"))]
1305   "TARGET_FPU
1306    && (register_operand (operands[0], SFmode)
1307        || register_operand (operands[1], SFmode))"
1308   "@
1309    fmovs %1,%0
1310    mov %1,%0
1311    st %r1,[%@-4]\;ld [%@-4],%0
1312    ld %1,%0
1313    ld %1,%0
1314    st %r1,%0
1315    st %r1,%0"
1316   [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store")])
1317
1318 ;; Exactly the same as above, except that all `f' cases are deleted.
1319 ;; This is necessary to prevent reload from ever trying to use a `f' reg
1320 ;; when -mno-fpu.
1321
1322 (define_insn ""
1323   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
1324         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
1325   "! TARGET_FPU
1326    && (register_operand (operands[0], SFmode)
1327        || register_operand (operands[1], SFmode))"
1328   "@
1329    mov %1,%0
1330    ld %1,%0
1331    st %r1,%0"
1332   [(set_attr "type" "move,load,store")])
1333
1334 (define_insn ""
1335   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
1336         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
1337    (clobber (match_scratch:SI 2 "=&r"))]
1338   ""
1339   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1340   [(set_attr "type" "store")
1341    (set_attr "length" "2")])
1342 \f
1343 ;;- zero extension instructions
1344
1345 ;; These patterns originally accepted general_operands, however, slightly
1346 ;; better code is generated by only accepting register_operands, and then
1347 ;; letting combine generate the ldu[hb] insns.
1348
1349 (define_expand "zero_extendhisi2"
1350   [(set (match_operand:SI 0 "register_operand" "")
1351         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
1352   ""
1353   "
1354 {
1355   rtx temp = gen_reg_rtx (SImode);
1356   rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1357
1358   if (GET_CODE (operand1) == SUBREG)
1359     operand1 = XEXP (operand1, 0);
1360
1361   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1362                           shift_16));
1363   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
1364   DONE;
1365 }")
1366
1367 (define_insn ""
1368   [(set (match_operand:SI 0 "register_operand" "=r")
1369         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1370   ""
1371   "lduh %1,%0"
1372   [(set_attr "type" "load")])
1373
1374 (define_expand "zero_extendqihi2"
1375   [(set (match_operand:HI 0 "register_operand" "")
1376         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1377   ""
1378   "")
1379
1380 (define_insn ""
1381   [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1382         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1383   "GET_CODE (operands[1]) != CONST_INT"
1384   "@
1385    and %1,0xff,%0;
1386    mov (%1 & 0xff),%0
1387    ldub %1,%0"
1388   [(set_attr "type" "unary,move,load")
1389    (set_attr "length" "1")])
1390
1391 (define_expand "zero_extendqisi2"
1392   [(set (match_operand:SI 0 "register_operand" "")
1393         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1394   ""
1395   "")
1396
1397 (define_insn ""
1398   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1399         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1400   "GET_CODE (operands[1]) != CONST_INT"
1401   "@
1402    and %1,0xff,%0
1403    mov (%1 & 0xff),%0
1404    ldub %1,%0"
1405   [(set_attr "type" "unary,move,load")
1406    (set_attr "length" "1")])
1407
1408 (define_insn ""
1409   [(set (reg:CC 0)
1410         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
1411                     (const_int 0)))]
1412   ""
1413   "andcc %0,0xff,%%g0"
1414   [(set_attr "type" "compare")])
1415
1416 (define_insn ""
1417   [(set (reg:CC 0)
1418         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1419                     (const_int 0)))
1420    (set (match_operand:SI 0 "register_operand" "=r")
1421         (zero_extend:SI (match_dup 1)))]
1422   ""
1423   "andcc %1,0xff,%0"
1424   [(set_attr "type" "unary")])
1425 \f
1426 ;;- sign extension instructions
1427
1428 ;; These patterns originally accepted general_operands, however, slightly
1429 ;; better code is generated by only accepting register_operands, and then
1430 ;; letting combine generate the lds[hb] insns.
1431
1432 (define_expand "extendhisi2"
1433   [(set (match_operand:SI 0 "register_operand" "")
1434         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1435   ""
1436   "
1437 {
1438   rtx temp = gen_reg_rtx (SImode);
1439   rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1440
1441   if (GET_CODE (operand1) == SUBREG)
1442     operand1 = XEXP (operand1, 0);
1443
1444   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1445                           shift_16));
1446   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
1447   DONE;
1448 }")
1449
1450 (define_insn ""
1451   [(set (match_operand:SI 0 "register_operand" "=r")
1452         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1453   ""
1454   "ldsh %1,%0"
1455   [(set_attr "type" "load")])
1456
1457 (define_expand "extendqihi2"
1458   [(set (match_operand:HI 0 "register_operand" "")
1459         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
1460   ""
1461   "
1462 {
1463   rtx temp = gen_reg_rtx (SImode);
1464   rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1465
1466   if (GET_CODE (operand1) == SUBREG)
1467     operand1 = XEXP (operand1, 0);
1468   if (GET_CODE (operand0) == SUBREG)
1469     operand0 = XEXP (operand0, 0);
1470   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1471                           shift_24));
1472   if (GET_MODE (operand0) != SImode)
1473     operand0 = gen_rtx (SUBREG, SImode, operand0, 0);
1474   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1475   DONE;
1476 }")
1477
1478 (define_insn ""
1479   [(set (match_operand:HI 0 "register_operand" "=r")
1480         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
1481   ""
1482   "ldsb %1,%0"
1483   [(set_attr "type" "load")])
1484
1485 (define_expand "extendqisi2"
1486   [(set (match_operand:SI 0 "register_operand" "")
1487         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
1488   ""
1489   "
1490 {
1491   rtx temp = gen_reg_rtx (SImode);
1492   rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1493
1494   if (GET_CODE (operand1) == SUBREG)
1495     operand1 = XEXP (operand1, 0);
1496   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1497                           shift_24));
1498   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1499   DONE;
1500 }")
1501
1502 (define_insn ""
1503   [(set (match_operand:SI 0 "register_operand" "=r")
1504         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1505   ""
1506   "ldsb %1,%0"
1507   [(set_attr "type" "load")])
1508 \f
1509 ;; Special pattern for optimizing bit-field compares.  This is needed
1510 ;; because combine uses this as a canonical form.
1511
1512 (define_insn ""
1513   [(set (reg:CC 0)
1514         (compare:CC
1515          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
1516                           (match_operand:SI 1 "small_int" "n")
1517                           (match_operand:SI 2 "small_int" "n"))
1518          (const_int 0)))]
1519   "INTVAL (operands[2]) > 19"
1520   "*
1521 {
1522   int len = INTVAL (operands[1]);
1523   int pos = 32 - INTVAL (operands[2]) - len;
1524   unsigned mask = ((1 << len) - 1) << pos;
1525
1526   operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
1527   return \"andcc %0,%1,%%g0\";
1528 }")
1529 \f
1530 ;; Conversions between float, double and long double.
1531
1532 (define_insn "extendsfdf2"
1533   [(set (match_operand:DF 0 "register_operand" "=f")
1534         (float_extend:DF
1535          (match_operand:SF 1 "register_operand" "f")))]
1536   "TARGET_FPU"
1537   "fstod %1,%0"
1538   [(set_attr "type" "fp")])
1539
1540 (define_insn "extendsftf2"
1541   [(set (match_operand:TF 0 "register_operand" "=f")
1542         (float_extend:TF
1543          (match_operand:SF 1 "register_operand" "f")))]
1544   "TARGET_FPU"
1545   "fstoq %1,%0"
1546   [(set_attr "type" "fp")])
1547
1548 (define_insn "extenddftf2"
1549   [(set (match_operand:TF 0 "register_operand" "=f")
1550         (float_extend:TF
1551          (match_operand:DF 1 "register_operand" "f")))]
1552   "TARGET_FPU"
1553   "fdtoq %1,%0"
1554   [(set_attr "type" "fp")])
1555
1556 (define_insn "truncdfsf2"
1557   [(set (match_operand:SF 0 "register_operand" "=f")
1558         (float_truncate:SF
1559          (match_operand:DF 1 "register_operand" "f")))]
1560   "TARGET_FPU"
1561   "fdtos %1,%0"
1562   [(set_attr "type" "fp")])
1563
1564 (define_insn "trunctfsf2"
1565   [(set (match_operand:SF 0 "register_operand" "=f")
1566         (float_truncate:SF
1567          (match_operand:TF 1 "register_operand" "f")))]
1568   "TARGET_FPU"
1569   "fqtos %1,%0"
1570   [(set_attr "type" "fp")])
1571
1572 (define_insn "trunctfdf2"
1573   [(set (match_operand:DF 0 "register_operand" "=f")
1574         (float_truncate:DF
1575          (match_operand:TF 1 "register_operand" "f")))]
1576   "TARGET_FPU"
1577   "fqtod %1,%0"
1578   [(set_attr "type" "fp")])
1579 \f
1580 ;; Conversion between fixed point and floating point.
1581
1582 (define_insn "floatsisf2"
1583   [(set (match_operand:SF 0 "register_operand" "=f")
1584         (float:SF (match_operand:SI 1 "register_operand" "f")))]
1585   "TARGET_FPU"
1586   "fitos %1,%0"
1587   [(set_attr "type" "fp")])
1588
1589 (define_insn "floatsidf2"
1590   [(set (match_operand:DF 0 "register_operand" "=f")
1591         (float:DF (match_operand:SI 1 "register_operand" "f")))]
1592   "TARGET_FPU"
1593   "fitod %1,%0"
1594   [(set_attr "type" "fp")])
1595
1596 (define_insn "floatsitf2"
1597   [(set (match_operand:TF 0 "register_operand" "=f")
1598         (float:TF (match_operand:SI 1 "register_operand" "f")))]
1599   "TARGET_FPU"
1600   "fitox %1,%0"
1601   [(set_attr "type" "fp")])
1602
1603 ;; Convert a float to an actual integer.
1604 ;; Truncation is performed as part of the conversion.
1605
1606 (define_insn "fix_truncsfsi2"
1607   [(set (match_operand:SI 0 "register_operand" "=f")
1608         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
1609   "TARGET_FPU"
1610   "fstoi %1,%0"
1611   [(set_attr "type" "fp")])
1612
1613 (define_insn "fix_truncdfsi2"
1614   [(set (match_operand:SI 0 "register_operand" "=f")
1615         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
1616   "TARGET_FPU"
1617   "fdtoi %1,%0"
1618   [(set_attr "type" "fp")])
1619
1620 (define_insn "fix_trunctfsi2"
1621   [(set (match_operand:SI 0 "register_operand" "=f")
1622         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))]
1623   "TARGET_FPU"
1624   "fqtoi %1,%0"
1625   [(set_attr "type" "fp")])
1626 \f
1627 ;;- arithmetic instructions
1628
1629 (define_insn "adddi3"
1630   [(set (match_operand:DI 0 "register_operand" "=r")
1631         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
1632                  (match_operand:DI 2 "arith_double_operand" "rHI")))
1633    (clobber (reg:SI 0))]
1634   ""
1635   "*
1636 {
1637   rtx op2 = operands[2];
1638
1639   /* If constant is positive, upper bits zeroed, otherwise unchanged.
1640      Give the assembler a chance to pick the move instruction. */
1641   if (GET_CODE (op2) == CONST_INT)
1642     {
1643       int sign = INTVAL (op2);
1644       if (sign < 0)
1645         return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1646       return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1647     }
1648   else if (GET_CODE (op2) == CONST_DOUBLE)
1649     {
1650       int sign = CONST_DOUBLE_HIGH (op2);
1651       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1652                              CONST_DOUBLE_LOW (operands[1]));
1653       if (sign < 0)
1654         return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1655       return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1656     }
1657   return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
1658 }"
1659   [(set_attr "length" "2")])
1660
1661 (define_insn "addsi3"
1662   [(set (match_operand:SI 0 "register_operand" "=r")
1663         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1664                  (match_operand:SI 2 "arith_operand" "rI")))]
1665   ""
1666   "add %1,%2,%0")
1667
1668 (define_insn ""
1669   [(set (reg:CC_NOOV 0)
1670         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
1671                                   (match_operand:SI 1 "arith_operand" "rI"))
1672                          (const_int 0)))]
1673   ""
1674   "addcc %0,%1,%%g0"
1675   [(set_attr "type" "compare")])
1676
1677 (define_insn ""
1678   [(set (reg:CC_NOOV 0)
1679         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1680                                   (match_operand:SI 2 "arith_operand" "rI"))
1681                          (const_int 0)))
1682    (set (match_operand:SI 0 "register_operand" "=r")
1683         (plus:SI (match_dup 1) (match_dup 2)))]
1684   ""
1685   "addcc %1,%2,%0")
1686
1687 (define_insn "subdi3"
1688   [(set (match_operand:DI 0 "register_operand" "=r")
1689         (minus:DI (match_operand:DI 1 "register_operand" "r")
1690                   (match_operand:DI 2 "arith_double_operand" "rHI")))
1691    (clobber (reg:SI 0))]
1692   ""
1693   "*
1694 {
1695   rtx op2 = operands[2];
1696
1697   /* If constant is positive, upper bits zeroed, otherwise unchanged.
1698      Give the assembler a chance to pick the move instruction. */
1699   if (GET_CODE (op2) == CONST_INT)
1700     {
1701       int sign = INTVAL (op2);
1702       if (sign < 0)
1703         return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1704       return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1705     }
1706   else if (GET_CODE (op2) == CONST_DOUBLE)
1707     {
1708       int sign = CONST_DOUBLE_HIGH (op2);
1709       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1710                              CONST_DOUBLE_LOW (operands[1]));
1711       if (sign < 0)
1712         return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1713       return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1714     }
1715   return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
1716 }"
1717   [(set_attr "length" "2")])
1718
1719 (define_insn "subsi3"
1720   [(set (match_operand:SI 0 "register_operand" "=r")
1721         (minus:SI (match_operand:SI 1 "register_operand" "r")
1722                   (match_operand:SI 2 "arith_operand" "rI")))]
1723   ""
1724   "sub %1,%2,%0")
1725
1726 (define_insn ""
1727   [(set (reg:CC_NOOV 0)
1728         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
1729                                    (match_operand:SI 1 "arith_operand" "rI"))
1730                          (const_int 0)))]
1731   ""
1732   "subcc %0,%1,%%g0"
1733   [(set_attr "type" "compare")])
1734
1735 (define_insn ""
1736   [(set (reg:CC_NOOV 0)
1737         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
1738                                    (match_operand:SI 2 "arith_operand" "rI"))
1739                          (const_int 0)))
1740    (set (match_operand:SI 0 "register_operand" "=r")
1741         (minus:SI (match_dup 1) (match_dup 2)))]
1742   ""
1743   "subcc %1,%2,%0")
1744
1745 (define_insn "mulsi3"
1746   [(set (match_operand:SI 0 "register_operand" "=r")
1747         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
1748                  (match_operand:SI 2 "arith_operand" "rI")))]
1749   "TARGET_V8 || TARGET_SPARCLITE"
1750   "smul %1,%2,%0")
1751
1752 ;; It is not known whether this will match.
1753
1754 (define_insn ""
1755   [(set (match_operand:SI 0 "register_operand" "=r")
1756         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
1757                  (match_operand:SI 2 "arith_operand" "rI")))
1758    (set (reg:CC_NOOV 0)
1759         (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
1760                          (const_int 0)))]
1761   "TARGET_V8 || TARGET_SPARCLITE"
1762   "smulcc %1,%2,%0")
1763
1764 (define_expand "mulsidi3"
1765   [(set (match_operand:DI 0 "register_operand" "")
1766         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1767                  (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
1768   "TARGET_V8 || TARGET_SPARCLITE"
1769   "
1770 {
1771   if (CONSTANT_P (operands[2]))
1772     {
1773       emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
1774       DONE;
1775     }
1776 }")
1777
1778 (define_insn ""
1779   [(set (match_operand:DI 0 "register_operand" "=r")
1780         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1781                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1782   "TARGET_V8 || TARGET_SPARCLITE"
1783   "smul %1,%2,%R0\;rd %%y,%0"
1784   [(set_attr "length" "2")])
1785
1786 ;; Extra pattern, because sign_extend of a constant isn't legal.
1787
1788 (define_insn "const_mulsidi3"
1789   [(set (match_operand:DI 0 "register_operand" "=r")
1790         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1791                  (match_operand:SI 2 "small_int" "I")))]
1792   "TARGET_V8 || TARGET_SPARCLITE"
1793   "smul %1,%2,%R0\;rd %%y,%0"
1794   [(set_attr "length" "2")])
1795
1796 (define_expand "umulsidi3"
1797   [(set (match_operand:DI 0 "register_operand" "")
1798         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1799                  (zero_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
1800   "TARGET_V8 || TARGET_SPARCLITE"
1801   "
1802 {
1803   if (CONSTANT_P (operands[2]))
1804     {
1805       emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
1806       DONE;
1807     }
1808 }")
1809
1810 (define_insn ""
1811   [(set (match_operand:DI 0 "register_operand" "=r")
1812         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1813                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1814   "TARGET_V8 || TARGET_SPARCLITE"
1815   "umul %1,%2,%R0\;rd %%y,%0"
1816   [(set_attr "length" "2")])
1817
1818 ;; Extra pattern, because sign_extend of a constant isn't legal.
1819
1820 (define_insn "const_umulsidi3"
1821   [(set (match_operand:DI 0 "register_operand" "=r")
1822         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1823                  (match_operand:SI 2 "small_int" "I")))]
1824   "TARGET_V8 || TARGET_SPARCLITE"
1825   "umul %1,%2,%R0\;rd %%y,%0"
1826   [(set_attr "length" "2")])
1827
1828 ;; The architecture specifies that there must be 3 instructions between
1829 ;; a y register write and a use of it for correct results.
1830
1831 (define_insn "divsi3"
1832   [(set (match_operand:SI 0 "register_operand" "=r")
1833         (div:SI (match_operand:SI 1 "register_operand" "r")
1834                 (match_operand:SI 2 "arith_operand" "rI")))
1835    (clobber (match_scratch:SI 3 "=&r"))]
1836   "TARGET_V8"
1837   "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0"
1838   [(set_attr "length" "6")])
1839
1840 ;; It is not known whether this will match.
1841
1842 (define_insn ""
1843   [(set (match_operand:SI 0 "register_operand" "=r")
1844         (div:SI (match_operand:SI 1 "register_operand" "r")
1845                 (match_operand:SI 2 "arith_operand" "rI")))
1846    (set (reg:CC 0)
1847         (compare:CC (div:SI (match_dup 1) (match_dup 2))
1848                     (const_int 0)))
1849    (clobber (match_scratch:SI 3 "=&r"))]
1850   "TARGET_V8"
1851   "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0"
1852   [(set_attr "length" "6")])
1853
1854 (define_insn "udivsi3"
1855   [(set (match_operand:SI 0 "register_operand" "=r")
1856         (udiv:SI (match_operand:SI 1 "register_operand" "r")
1857                 (match_operand:SI 2 "arith_operand" "rI")))]
1858   "TARGET_V8"
1859   "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0"
1860   [(set_attr "length" "5")])
1861
1862 ;; It is not known whether this will match.
1863
1864 (define_insn ""
1865   [(set (match_operand:SI 0 "register_operand" "=r")
1866         (udiv:SI (match_operand:SI 1 "register_operand" "r")
1867                 (match_operand:SI 2 "arith_operand" "rI")))
1868    (set (reg:CC 0)
1869         (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
1870                     (const_int 0)))]
1871   "TARGET_V8"
1872   "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0"
1873   [(set_attr "length" "5")])
1874
1875 ;;- and instructions
1876 ;; We define DImode `and` so with DImode `not` we can get
1877 ;; DImode `andn`.  Other combinations are possible.
1878
1879 (define_expand "anddi3"
1880   [(set (match_operand:DI 0 "register_operand" "")
1881         (and:DI (match_operand:DI 1 "arith_double_operand" "")
1882                 (match_operand:DI 2 "arith_double_operand" "")))]
1883   ""
1884   "")
1885
1886 (define_insn ""
1887   [(set (match_operand:DI 0 "register_operand" "=r")
1888         (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
1889                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1890   ""
1891   "*
1892 {
1893   rtx op2 = operands[2];
1894
1895   /* If constant is positive, upper bits zeroed, otherwise unchanged.
1896      Give the assembler a chance to pick the move instruction. */
1897   if (GET_CODE (op2) == CONST_INT)
1898     {
1899       int sign = INTVAL (op2);
1900       if (sign < 0)
1901         return \"mov %1,%0\;and %R1,%2,%R0\";
1902       return \"mov 0,%0\;and %R1,%2,%R0\";
1903     }
1904   else if (GET_CODE (op2) == CONST_DOUBLE)
1905     {
1906       int sign = CONST_DOUBLE_HIGH (op2);
1907       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1908                              CONST_DOUBLE_LOW (operands[1]));
1909       if (sign < 0)
1910         return \"mov %1,%0\;and %R1,%2,%R0\";
1911       return \"mov 0,%0\;and %R1,%2,%R0\";
1912     }
1913   return \"and %1,%2,%0\;and %R1,%R2,%R0\";
1914 }"
1915   [(set_attr "length" "2")])
1916
1917 (define_insn "andsi3"
1918   [(set (match_operand:SI 0 "register_operand" "=r")
1919         (and:SI (match_operand:SI 1 "arith_operand" "%r")
1920                 (match_operand:SI 2 "arith_operand" "rI")))]
1921   ""
1922   "and %1,%2,%0")
1923
1924 (define_split
1925   [(set (match_operand:SI 0 "register_operand" "")
1926         (and:SI (match_operand:SI 1 "register_operand" "")
1927                 (match_operand:SI 2 "" "")))
1928    (clobber (match_operand:SI 3 "register_operand" ""))]
1929   "GET_CODE (operands[2]) == CONST_INT
1930    && !SMALL_INT (operands[2])
1931    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
1932   [(set (match_dup 3) (match_dup 4))
1933    (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
1934   "
1935 {
1936   operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
1937 }")
1938
1939 (define_insn ""
1940   [(set (match_operand:DI 0 "register_operand" "=r")
1941         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1942                 (match_operand:DI 2 "register_operand" "r")))]
1943   ""
1944   "andn %2,%1,%0\;andn %R2,%R1,%R0"
1945   [(set_attr "length" "2")])
1946
1947 (define_insn ""
1948   [(set (match_operand:SI 0 "register_operand" "=r")
1949         (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1950                 (match_operand:SI 2 "register_operand" "r")))]
1951   ""
1952   "andn %2,%1,%0")
1953
1954 (define_expand "iordi3"
1955   [(set (match_operand:DI 0 "register_operand" "")
1956         (ior:DI (match_operand:DI 1 "arith_double_operand" "")
1957                 (match_operand:DI 2 "arith_double_operand" "")))]
1958   ""
1959   "")
1960
1961 (define_insn ""
1962   [(set (match_operand:DI 0 "register_operand" "=r")
1963         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
1964                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1965   ""
1966   "*
1967 {
1968   rtx op2 = operands[2];
1969
1970   /* If constant is positive, upper bits zeroed, otherwise unchanged.
1971      Give the assembler a chance to pick the move instruction. */
1972   if (GET_CODE (op2) == CONST_INT)
1973     {
1974       int sign = INTVAL (op2);
1975       if (sign < 0)
1976         return \"mov -1,%0\;or %R1,%2,%R0\";
1977       return \"mov %1,%0\;or %R1,%2,%R0\";
1978     }
1979   else if (GET_CODE (op2) == CONST_DOUBLE)
1980     {
1981       int sign = CONST_DOUBLE_HIGH (op2);
1982       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1983                              CONST_DOUBLE_LOW (operands[1]));
1984       if (sign < 0)
1985         return \"mov -1,%0\;or %R1,%2,%R0\";
1986       return \"mov %1,%0\;or %R1,%2,%R0\";
1987     }
1988   return \"or %1,%2,%0\;or %R1,%R2,%R0\";
1989 }"
1990   [(set_attr "length" "2")])
1991
1992 (define_insn "iorsi3"
1993   [(set (match_operand:SI 0 "register_operand" "=r")
1994         (ior:SI (match_operand:SI 1 "arith_operand" "%r")
1995                 (match_operand:SI 2 "arith_operand" "rI")))]
1996   ""
1997   "or %1,%2,%0")
1998
1999 (define_split
2000   [(set (match_operand:SI 0 "register_operand" "")
2001         (ior:SI (match_operand:SI 1 "register_operand" "")
2002                 (match_operand:SI 2 "" "")))
2003    (clobber (match_operand:SI 3 "register_operand" ""))]
2004   "GET_CODE (operands[2]) == CONST_INT
2005    && !SMALL_INT (operands[2])
2006    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2007   [(set (match_dup 3) (match_dup 4))
2008    (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
2009   "
2010 {
2011   operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2012 }")
2013
2014 (define_insn ""
2015   [(set (match_operand:DI 0 "register_operand" "=r")
2016         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
2017                 (match_operand:DI 2 "register_operand" "r")))]
2018   ""
2019   "orn %2,%1,%0\;orn %R2,%R1,%R0"
2020   [(set_attr "length" "2")])
2021
2022 (define_insn ""
2023   [(set (match_operand:SI 0 "register_operand" "=r")
2024         (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
2025                 (match_operand:SI 2 "register_operand" "r")))]
2026   ""
2027   "orn %2,%1,%0")
2028
2029 (define_expand "xordi3"
2030   [(set (match_operand:DI 0 "register_operand" "")
2031         (xor:DI (match_operand:DI 1 "arith_double_operand" "")
2032                 (match_operand:DI 2 "arith_double_operand" "")))]
2033   ""
2034   "")
2035
2036 (define_insn ""
2037   [(set (match_operand:DI 0 "register_operand" "=r")
2038         (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
2039                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
2040   ""
2041   "*
2042 {
2043   rtx op2 = operands[2];
2044
2045   /* If constant is positive, upper bits zeroed, otherwise unchanged.
2046      Give the assembler a chance to pick the move instruction. */
2047   if (GET_CODE (op2) == CONST_INT)
2048     {
2049       int sign = INTVAL (op2);
2050       if (sign < 0)
2051         return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
2052       return \"mov %1,%0\;xor %R1,%2,%R0\";
2053     }
2054   else if (GET_CODE (op2) == CONST_DOUBLE)
2055     {
2056       int sign = CONST_DOUBLE_HIGH (op2);
2057       operands[2] = gen_rtx (CONST_INT, VOIDmode,
2058                              CONST_DOUBLE_LOW (operands[1]));
2059       if (sign < 0)
2060         return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
2061       return \"mov %1,%0\;xor %R1,%2,%R0\";
2062     }
2063   return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
2064 }"
2065   [(set_attr "length" "2")])
2066
2067 (define_insn "xorsi3"
2068   [(set (match_operand:SI 0 "register_operand" "=r")
2069         (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
2070                 (match_operand:SI 2 "arith_operand" "rI")))]
2071   ""
2072   "xor %r1,%2,%0")
2073
2074 (define_split
2075   [(set (match_operand:SI 0 "register_operand" "")
2076         (xor:SI (match_operand:SI 1 "register_operand" "")
2077                 (match_operand:SI 2 "" "")))
2078    (clobber (match_operand:SI 3 "register_operand" ""))]
2079   "GET_CODE (operands[2]) == CONST_INT
2080    && !SMALL_INT (operands[2])
2081    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2082   [(set (match_dup 3) (match_dup 4))
2083    (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
2084   "
2085 {
2086   operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2087 }")
2088
2089 (define_split
2090   [(set (match_operand:SI 0 "register_operand" "")
2091         (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
2092                         (match_operand:SI 2 "" ""))))
2093    (clobber (match_operand:SI 3 "register_operand" ""))]
2094   "GET_CODE (operands[2]) == CONST_INT
2095    && !SMALL_INT (operands[2])
2096    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2097   [(set (match_dup 3) (match_dup 4))
2098    (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
2099   "
2100 {
2101   operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2102 }")
2103
2104 ;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
2105 ;; Combine now canonicalizes to the rightmost expression.
2106 (define_insn ""
2107   [(set (match_operand:DI 0 "register_operand" "=r")
2108         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
2109                         (match_operand:DI 2 "register_operand" "r"))))]
2110   ""
2111   "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
2112   [(set_attr "length" "2")])
2113
2114 (define_insn ""
2115   [(set (match_operand:SI 0 "register_operand" "=r")
2116         (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
2117                         (match_operand:SI 2 "arith_operand" "rI"))))]
2118   ""
2119   "xnor %r1,%2,%0")
2120
2121 ;; These correspond to the above in the case where we also (or only)
2122 ;; want to set the condition code.  
2123
2124 (define_insn ""
2125   [(set (reg:CC 0)
2126         (compare:CC
2127          (match_operator:SI 2 "cc_arithop"
2128                             [(match_operand:SI 0 "arith_operand" "%r")
2129                              (match_operand:SI 1 "arith_operand" "rI")])
2130          (const_int 0)))]
2131   ""
2132   "%A2cc %0,%1,%%g0"
2133   [(set_attr "type" "compare")])
2134
2135 (define_insn ""
2136   [(set (reg:CC 0)
2137         (compare:CC
2138          (match_operator:SI 3 "cc_arithop"
2139                             [(match_operand:SI 1 "arith_operand" "%r")
2140                              (match_operand:SI 2 "arith_operand" "rI")])
2141          (const_int 0)))
2142    (set (match_operand:SI 0 "register_operand" "=r")
2143         (match_dup 3))]
2144   ""
2145   "%A3cc %1,%2,%0")
2146
2147 (define_insn ""
2148   [(set (reg:CC 0)
2149         (compare:CC
2150          (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
2151                          (match_operand:SI 1 "arith_operand" "rI")))
2152          (const_int 0)))]
2153   ""
2154   "xnorcc %r0,%1,%%g0"
2155   [(set_attr "type" "compare")])
2156
2157 (define_insn ""
2158   [(set (reg:CC 0)
2159         (compare:CC
2160          (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
2161                          (match_operand:SI 2 "arith_operand" "rI")))
2162          (const_int 0)))
2163    (set (match_operand:SI 0 "register_operand" "=r")
2164         (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
2165   ""
2166   "xnorcc %r1,%2,%0")
2167
2168 (define_insn ""
2169   [(set (reg:CC 0)
2170         (compare:CC
2171          (match_operator:SI 2 "cc_arithopn"
2172                             [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
2173                              (match_operand:SI 1 "reg_or_0_operand" "rJ")])
2174          (const_int 0)))]
2175   ""
2176   "%B2cc %r1,%0,%%g0"
2177   [(set_attr "type" "compare")])
2178
2179 (define_insn ""
2180   [(set (reg:CC 0)
2181         (compare:CC
2182          (match_operator:SI 3 "cc_arithopn"
2183                             [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
2184                              (match_operand:SI 2 "reg_or_0_operand" "rJ")])
2185          (const_int 0)))
2186    (set (match_operand:SI 0 "register_operand" "=r")
2187         (match_dup 3))]
2188   ""
2189   "%B3cc %r2,%1,%0")
2190
2191 ;; We cannot use the "neg" pseudo insn because the Sun assembler
2192 ;; does not know how to make it work for constants.
2193
2194 (define_insn "negdi2"
2195   [(set (match_operand:DI 0 "register_operand" "=r")
2196         (neg:DI (match_operand:DI 1 "register_operand" "r")))
2197    (clobber (reg:SI 0))]
2198   ""
2199   "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
2200   [(set_attr "type" "unary")
2201    (set_attr "length" "2")])
2202
2203 (define_insn "negsi2"
2204   [(set (match_operand:SI 0 "general_operand" "=r")
2205         (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
2206   ""
2207   "sub %%g0,%1,%0"
2208   [(set_attr "type" "unary")])
2209
2210 (define_insn ""
2211   [(set (reg:CC_NOOV 0)
2212         (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
2213                          (const_int 0)))]
2214   ""
2215   "subcc %%g0,%0,%%g0"
2216   [(set_attr "type" "compare")])
2217
2218 (define_insn ""
2219   [(set (reg:CC_NOOV 0)
2220         (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
2221                          (const_int 0)))
2222    (set (match_operand:SI 0 "register_operand" "=r")
2223         (neg:SI (match_dup 1)))]
2224   ""
2225   "subcc %%g0,%1,%0"
2226   [(set_attr "type" "unary")])
2227
2228 ;; We cannot use the "not" pseudo insn because the Sun assembler
2229 ;; does not know how to make it work for constants.
2230 (define_expand "one_cmpldi2"
2231   [(set (match_operand:DI 0 "register_operand" "=r")
2232         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
2233   ""
2234   "")
2235
2236 (define_insn ""
2237   [(set (match_operand:DI 0 "register_operand" "=r")
2238         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
2239   ""
2240   "*
2241 {
2242   rtx op1 = operands[1];
2243
2244   if (GET_CODE (op1) == CONST_INT)
2245     {
2246       int sign = INTVAL (op1);
2247       if (sign < 0)
2248         return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
2249       return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
2250     }
2251   else if (GET_CODE (op1) == CONST_DOUBLE)
2252     {
2253       int sign = CONST_DOUBLE_HIGH (op1);
2254       operands[1] = gen_rtx (CONST_INT, VOIDmode,
2255                              CONST_DOUBLE_LOW (operands[1]));
2256       if (sign < 0)
2257         return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
2258       return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
2259     }
2260   return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\";
2261 }"
2262   [(set_attr "type" "unary")
2263    (set_attr "length" "2")])
2264
2265 (define_insn "one_cmplsi2"
2266   [(set (match_operand:SI 0 "register_operand" "=r")
2267         (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
2268   ""
2269   "xnor %%g0,%1,%0"
2270   [(set_attr "type" "unary")])
2271
2272 (define_insn ""
2273   [(set (reg:CC 0)
2274         (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
2275                     (const_int 0)))]
2276   ""
2277   "xnorcc %%g0,%0,%%g0"
2278   [(set_attr "type" "compare")])
2279
2280 (define_insn ""
2281   [(set (reg:CC 0)
2282         (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
2283                     (const_int 0)))
2284    (set (match_operand:SI 0 "register_operand" "=r")
2285         (not:SI (match_dup 1)))]
2286   ""
2287   "xnorcc %%g0,%1,%0"
2288   [(set_attr "type" "unary")])
2289 \f
2290 ;; Floating point arithmetic instructions.
2291
2292 (define_insn "addtf3"
2293   [(set (match_operand:TF 0 "register_operand" "=f")
2294         (plus:TF (match_operand:TF 1 "register_operand" "f")
2295                  (match_operand:TF 2 "register_operand" "f")))]
2296   "TARGET_FPU"
2297   "faddq %1,%2,%0"
2298   [(set_attr "type" "fp")])
2299
2300 (define_insn "adddf3"
2301   [(set (match_operand:DF 0 "register_operand" "=f")
2302         (plus:DF (match_operand:DF 1 "register_operand" "f")
2303                  (match_operand:DF 2 "register_operand" "f")))]
2304   "TARGET_FPU"
2305   "faddd %1,%2,%0"
2306   [(set_attr "type" "fp")])
2307
2308 (define_insn "addsf3"
2309   [(set (match_operand:SF 0 "register_operand" "=f")
2310         (plus:SF (match_operand:SF 1 "register_operand" "f")
2311                  (match_operand:SF 2 "register_operand" "f")))]
2312   "TARGET_FPU"
2313   "fadds %1,%2,%0"
2314   [(set_attr "type" "fp")])
2315
2316 (define_insn "subtf3"
2317   [(set (match_operand:TF 0 "register_operand" "=f")
2318         (minus:TF (match_operand:TF 1 "register_operand" "f")
2319                   (match_operand:TF 2 "register_operand" "f")))]
2320   "TARGET_FPU"
2321   "fsubq %1,%2,%0"
2322   [(set_attr "type" "fp")])
2323
2324 (define_insn "subdf3"
2325   [(set (match_operand:DF 0 "register_operand" "=f")
2326         (minus:DF (match_operand:DF 1 "register_operand" "f")
2327                   (match_operand:DF 2 "register_operand" "f")))]
2328   "TARGET_FPU"
2329   "fsubd %1,%2,%0"
2330   [(set_attr "type" "fp")])
2331
2332 (define_insn "subsf3"
2333   [(set (match_operand:SF 0 "register_operand" "=f")
2334         (minus:SF (match_operand:SF 1 "register_operand" "f")
2335                   (match_operand:SF 2 "register_operand" "f")))]
2336   "TARGET_FPU"
2337   "fsubs %1,%2,%0"
2338   [(set_attr "type" "fp")])
2339
2340 (define_insn "multf3"
2341   [(set (match_operand:TF 0 "register_operand" "=f")
2342         (mult:TF (match_operand:TF 1 "register_operand" "f")
2343                  (match_operand:TF 2 "register_operand" "f")))]
2344   "TARGET_FPU"
2345   "fmulq %1,%2,%0"
2346   [(set_attr "type" "fpmul")])
2347
2348 (define_insn "muldf3"
2349   [(set (match_operand:DF 0 "register_operand" "=f")
2350         (mult:DF (match_operand:DF 1 "register_operand" "f")
2351                  (match_operand:DF 2 "register_operand" "f")))]
2352   "TARGET_FPU"
2353   "fmuld %1,%2,%0"
2354   [(set_attr "type" "fpmul")])
2355
2356 (define_insn "mulsf3"
2357   [(set (match_operand:SF 0 "register_operand" "=f")
2358         (mult:SF (match_operand:SF 1 "register_operand" "f")
2359                  (match_operand:SF 2 "register_operand" "f")))]
2360   "TARGET_FPU"
2361   "fmuls %1,%2,%0"
2362   [(set_attr "type" "fpmul")])
2363
2364 (define_insn ""
2365   [(set (match_operand:DF 0 "register_operand" "=f")
2366         (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
2367                  (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
2368   "TARGET_V8 && TARGET_FPU"
2369   "fsmuld %1,%2,%0"
2370   [(set_attr "type" "fpmul")])
2371
2372 (define_insn ""
2373   [(set (match_operand:TF 0 "register_operand" "=f")
2374         (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "f"))
2375                  (float_extend:TF (match_operand:DF 2 "register_operand" "f"))))]
2376   "TARGET_V8 && TARGET_FPU"
2377   "fdmulq %1,%2,%0"
2378   [(set_attr "type" "fpmul")])
2379
2380 (define_insn "divtf3"
2381   [(set (match_operand:TF 0 "register_operand" "=f")
2382         (div:TF (match_operand:TF 1 "register_operand" "f")
2383                 (match_operand:TF 2 "register_operand" "f")))]
2384   "TARGET_FPU"
2385   "fdivq %1,%2,%0"
2386   [(set_attr "type" "fpdiv")])
2387
2388 (define_insn "divdf3"
2389   [(set (match_operand:DF 0 "register_operand" "=f")
2390         (div:DF (match_operand:DF 1 "register_operand" "f")
2391                 (match_operand:DF 2 "register_operand" "f")))]
2392   "TARGET_FPU"
2393   "fdivd %1,%2,%0"
2394   [(set_attr "type" "fpdiv")])
2395
2396 (define_insn "divsf3"
2397   [(set (match_operand:SF 0 "register_operand" "=f")
2398         (div:SF (match_operand:SF 1 "register_operand" "f")
2399                 (match_operand:SF 2 "register_operand" "f")))]
2400   "TARGET_FPU"
2401   "fdivs %1,%2,%0"
2402   [(set_attr "type" "fpdiv")])
2403
2404 (define_insn "negtf2"
2405   [(set (match_operand:TF 0 "register_operand" "=f,f")
2406         (neg:TF (match_operand:TF 1 "register_operand" "0,f")))]
2407   "TARGET_FPU"
2408   "@
2409    fnegs %0,%0
2410    fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2411   [(set_attr "type" "fp")
2412    (set_attr "length" "1,4")])
2413
2414 (define_insn "negdf2"
2415   [(set (match_operand:DF 0 "register_operand" "=f,f")
2416         (neg:DF (match_operand:DF 1 "register_operand" "0,f")))]
2417   "TARGET_FPU"
2418   "@
2419    fnegs %0,%0
2420    fnegs %1,%0\;fmovs %R1,%R0"
2421   [(set_attr "type" "fp")
2422    (set_attr "length" "1,2")])
2423
2424 (define_insn "negsf2"
2425   [(set (match_operand:SF 0 "register_operand" "=f")
2426         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
2427   "TARGET_FPU"
2428   "fnegs %1,%0"
2429   [(set_attr "type" "fp")])
2430
2431 (define_insn "abstf2"
2432   [(set (match_operand:TF 0 "register_operand" "=f,f")
2433         (abs:TF (match_operand:TF 1 "register_operand" "0,f")))]
2434   "TARGET_FPU"
2435   "@
2436    fabss %0,%0
2437    fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2438   [(set_attr "type" "fp")
2439    (set_attr "length" "1,4")])
2440
2441 (define_insn "absdf2"
2442   [(set (match_operand:DF 0 "register_operand" "=f,f")
2443         (abs:DF (match_operand:DF 1 "register_operand" "0,f")))]
2444   "TARGET_FPU"
2445   "@
2446    fabss %0,%0
2447    fabss %1,%0\;fmovs %R1,%R0"
2448   [(set_attr "type" "fp")
2449    (set_attr "length" "1,2")])
2450
2451 (define_insn "abssf2"
2452   [(set (match_operand:SF 0 "register_operand" "=f")
2453         (abs:SF (match_operand:SF 1 "register_operand" "f")))]
2454   "TARGET_FPU"
2455   "fabss %1,%0"
2456   [(set_attr "type" "fp")])
2457
2458 (define_insn "sqrttf2"
2459   [(set (match_operand:TF 0 "register_operand" "=f")
2460         (sqrt:TF (match_operand:TF 1 "register_operand" "f")))]
2461   "TARGET_FPU"
2462   "fsqrtq %1,%0"
2463   [(set_attr "type" "fpsqrt")])
2464
2465 (define_insn "sqrtdf2"
2466   [(set (match_operand:DF 0 "register_operand" "=f")
2467         (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
2468   "TARGET_FPU"
2469   "fsqrtd %1,%0"
2470   [(set_attr "type" "fpsqrt")])
2471
2472 (define_insn "sqrtsf2"
2473   [(set (match_operand:SF 0 "register_operand" "=f")
2474         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
2475   "TARGET_FPU"
2476   "fsqrts %1,%0"
2477   [(set_attr "type" "fpsqrt")])
2478 \f
2479 ;;- arithmetic shift instructions
2480
2481 ;; We can trivially handle shifting the constant 1 by 64 bits.
2482 ;; For other shifts we use the library routine.
2483 ;; ??? Questionable, we can do better than this can't we?
2484 (define_expand "ashldi3"
2485   [(parallel [(set (match_operand:DI 0 "register_operand" "")
2486                    (ashift:DI (match_operand:DI 1 "const_double_operand" "")
2487                               (match_operand:SI 2 "register_operand" "")))
2488               (clobber (reg:SI 0))])]
2489   ""
2490   "
2491 {
2492   if (GET_CODE (operands[1]) == CONST_DOUBLE
2493       && CONST_DOUBLE_HIGH (operands[1]) == 0
2494       && CONST_DOUBLE_LOW (operands[1]) == 1)
2495     operands[1] = const1_rtx;
2496   else if (operands[1] != const1_rtx)
2497     FAIL;
2498 }")
2499
2500 ;; ??? Questionable, we can do better than this can't we?
2501 (define_insn ""
2502   [(set (match_operand:DI 0 "register_operand" "=&r")
2503         (ashift:DI (const_int 1)
2504                    (match_operand:SI 1 "register_operand" "r")))
2505    (clobber (reg:SI 0))]
2506   ""
2507   "subcc %1,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%1,%R0\;sll %0,%1,%0"
2508   [(set_attr "type" "multi")
2509    (set_attr "length" "5")])
2510
2511 (define_insn "ashlsi3"
2512   [(set (match_operand:SI 0 "register_operand" "=r")
2513         (ashift:SI (match_operand:SI 1 "register_operand" "r")
2514                    (match_operand:SI 2 "arith_operand" "rI")))]
2515   ""
2516   "sll %1,%2,%0")
2517
2518 (define_insn "ashrsi3"
2519   [(set (match_operand:SI 0 "register_operand" "=r")
2520         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
2521                      (match_operand:SI 2 "arith_operand" "rI")))]
2522   ""
2523   "sra %1,%2,%0")
2524
2525 (define_insn "lshrsi3"
2526   [(set (match_operand:SI 0 "register_operand" "=r")
2527         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
2528                      (match_operand:SI 2 "arith_operand" "rI")))]
2529   ""
2530   "srl %1,%2,%0")
2531 \f
2532 ;; Unconditional and other jump instructions
2533 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
2534 ;; following insn is never executed.  This saves us a nop.  Dbx does not
2535 ;; handle such branches though, so we only use them when optimizing.
2536 (define_insn "jump"
2537   [(set (pc) (label_ref (match_operand 0 "" "")))]
2538   ""
2539   "b%* %l0%("
2540   [(set_attr "type" "uncond_branch")])
2541
2542 (define_expand "tablejump"
2543   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2544               (use (label_ref (match_operand 1 "" "")))])]
2545   ""
2546   "
2547 {
2548   /* We need to use the PC value in %o7 that was set up when the address
2549      of the label was loaded into a register, so we need different RTL.  */
2550   if (flag_pic)
2551     {
2552       emit_insn (gen_pic_tablejump (operands[0], operands[1]));
2553       DONE;
2554     }
2555 }")
2556
2557 (define_insn "pic_tablejump"
2558   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2559    (use (label_ref (match_operand 1 "" "")))
2560    (use (reg:SI 15))]
2561   ""
2562   "jmp %%o7+%0%#"
2563   [(set_attr "type" "uncond_branch")])
2564
2565 (define_insn ""
2566   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2567    (use (label_ref (match_operand 1 "" "")))]
2568   ""
2569   "jmp %a0%#"
2570   [(set_attr "type" "uncond_branch")])
2571
2572 (define_insn ""
2573   [(set (pc) (label_ref (match_operand 0 "" "")))
2574    (set (reg:SI 15) (label_ref (match_dup 0)))]
2575   ""
2576   "call %l0%#"
2577   [(set_attr "type" "uncond_branch")])
2578
2579 ;; This pattern recognizes the "instruction" that appears in 
2580 ;; a function call that wants a structure value, 
2581 ;; to inform the called function if compiled with Sun CC.
2582 ;(define_insn ""
2583 ;  [(match_operand:SI 0 "immediate_operand" "")]
2584 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
2585 ;  "unimp %0"
2586 ;  [(set_attr "type" "marker")])
2587
2588 ;;- jump to subroutine
2589 (define_expand "call"
2590   ;; Note that this expression is not used for generating RTL.
2591   ;; All the RTL is generated explicitly below.
2592   [(call (match_operand:SI 0 "call_operand" "")
2593          (match_operand 3 "" "i"))]
2594   ;; operands[2] is next_arg_register
2595   ;; operands[3] is struct_value_size_rtx.
2596   ""
2597   "
2598 {
2599   rtx fn_rtx, nregs_rtx;
2600
2601   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
2602     {
2603       /* This is really a PIC sequence.  We want to represent
2604          it as a funny jump so it's delay slots can be filled. 
2605
2606          ??? But if this really *is* a CALL, will not it clobber the
2607          call-clobbered registers?  We lose this if it is a JUMP_INSN.
2608          Why cannot we have delay slots filled if it were a CALL?  */
2609
2610       if (INTVAL (operands[3]) > 0)
2611         emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2612                                  gen_rtx (SET, VOIDmode, pc_rtx,
2613                                           XEXP (operands[0], 0)),
2614                                  operands[3],
2615                                  gen_rtx (CLOBBER, VOIDmode,
2616                                           gen_rtx (REG, SImode, 15)))));
2617       else
2618         emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2619                                  gen_rtx (SET, VOIDmode, pc_rtx,
2620                                           XEXP (operands[0], 0)),
2621                                  gen_rtx (CLOBBER, VOIDmode,
2622                                           gen_rtx (REG, SImode, 15)))));
2623       goto finish_call;
2624     }
2625
2626   fn_rtx = operands[0];
2627
2628   /* Count the number of parameter registers being used by this call.
2629      if that argument is NULL, it means we are using them all, which
2630      means 6 on the sparc.  */
2631 #if 0
2632   if (operands[2])
2633     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
2634   else
2635     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2636 #else
2637   nregs_rtx = const0_rtx;
2638 #endif
2639
2640   if (INTVAL (operands[3]) > 0)
2641     emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2642                              gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2643                              operands[3],
2644                              gen_rtx (CLOBBER, VOIDmode,
2645                                                gen_rtx (REG, SImode, 15)))));
2646   else
2647     emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2648                              gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2649                              gen_rtx (CLOBBER, VOIDmode,
2650                                                gen_rtx (REG, SImode, 15)))));
2651
2652  finish_call:
2653 #if 0
2654   /* If this call wants a structure value,
2655      emit an unimp insn to let the called function know about this.  */
2656   if (INTVAL (operands[3]) > 0)
2657     {
2658       rtx insn = emit_insn (operands[3]);
2659       SCHED_GROUP_P (insn) = 1;
2660     }
2661 #endif
2662
2663   DONE;
2664 }")
2665
2666 (define_insn ""
2667   [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2668          (match_operand 1 "" ""))
2669    (clobber (reg:SI 15))]
2670   ;;- Do not use operand 1 for most machines.
2671   ""
2672   "*
2673 {
2674   return \"call %a0,%1%#\";
2675 }"
2676   [(set_attr "type" "call")])
2677
2678 ;; This is a call that wants a structure value.
2679 (define_insn ""
2680   [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2681          (match_operand 1 "" ""))
2682    (match_operand 2 "immediate_operand" "")
2683    (clobber (reg:SI 15))]
2684   ;;- Do not use operand 1 for most machines.
2685   "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
2686   "*
2687 {
2688   return \"call %a0,%1\;nop\;unimp %2\";
2689 }"
2690   [(set_attr "type" "call_no_delay_slot")])
2691
2692 (define_expand "call_value"
2693   [(set (match_operand 0 "register_operand" "=rf")
2694         (call (match_operand:SI 1 "" "")
2695               (match_operand 4 "" "")))]
2696   ;; operand 3 is next_arg_register
2697   ""
2698   "
2699 {
2700   rtx fn_rtx, nregs_rtx;
2701   rtvec vec;
2702
2703   fn_rtx = operands[1];
2704
2705 #if 0
2706   if (operands[3])
2707     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
2708   else
2709     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2710 #else
2711   nregs_rtx = const0_rtx;
2712 #endif
2713
2714   vec = gen_rtvec (2,
2715                    gen_rtx (SET, VOIDmode, operands[0],
2716                             gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2717                    gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15)));
2718
2719   emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2720
2721   DONE;
2722 }")
2723
2724 (define_insn ""
2725   [(set (match_operand 0 "" "=rf")
2726         (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS"))
2727               (match_operand 2 "" "")))
2728    (clobber (reg:SI 15))]
2729   ;;- Do not use operand 2 for most machines.
2730   ""
2731   "*
2732 {
2733   return \"call %a1,%2%#\";
2734 }"
2735   [(set_attr "type" "call")])
2736 \f
2737 (define_insn "return"
2738   [(return)]
2739   "! TARGET_EPILOGUE"
2740   "* return output_return (operands);"
2741   [(set_attr "type" "multi")])
2742
2743 (define_insn "nop"
2744   [(const_int 0)]
2745   ""
2746   "nop")
2747
2748 (define_insn "indirect_jump"
2749   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2750   ""
2751  "jmp %a0%#"
2752  [(set_attr "type" "uncond_branch")])
2753  
2754 (define_expand "nonlocal_goto"
2755   [(match_operand:SI 0 "general_operand" "")
2756    (match_operand:SI 1 "general_operand" "")
2757    (match_operand:SI 2 "general_operand" "")
2758    (match_operand:SI 3 "" "")]
2759   ""
2760   "
2761 {
2762   /* Trap instruction to flush all the registers window.  */
2763   emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2764                       gen_rtvec (1, const0_rtx), 0));
2765   /* Load the fp value for the containing fn into %fp.
2766      This is needed because operands[2] refers to %fp.
2767      Virtual register instantiation fails if the virtual %fp isn't set from a
2768      register.  Thus we must copy operands[0] into a register if it isn't
2769      already one.  */
2770   if (GET_CODE (operands[0]) != REG)
2771     operands[0] = force_reg (SImode, operands[0]);
2772   emit_move_insn (virtual_stack_vars_rtx, operands[0]);
2773   /* Find the containing function's current nonlocal goto handler,
2774      which will do any cleanups and then jump to the label.  */
2775   emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]);
2776   /* Restore %fp from stack pointer value for containing function.
2777      The restore insn that follows will move this to %sp,
2778      and reload the appropriate value into %fp.  */
2779   emit_move_insn (frame_pointer_rtx, operands[2]);
2780   /* Put in the static chain register the nonlocal label address.  */
2781   emit_move_insn (static_chain_rtx, operands[3]);
2782   /* USE of frame_pointer_rtx added for consistency; not clear if
2783      really needed.  */
2784   emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
2785   emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
2786   emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
2787   emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8)));
2788   /* Return, restoring reg window and jumping to goto handler.  */
2789   emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2790                       gen_rtvec (1, const0_rtx), 1));
2791   DONE;
2792 }")
2793
2794 ;; Special trap insn to flush register windows.
2795 (define_insn ""
2796   [(unspec_volatile [(const_int 0)] 0)]
2797   ""
2798   "ta 3"
2799   [(set_attr "type" "misc")])
2800
2801 (define_insn ""
2802   [(unspec_volatile [(const_int 0)] 1)]
2803   ""
2804   "jmp %%o0+0\;restore"
2805   [(set_attr "type" "misc")
2806    (set_attr "length" "2")])
2807 \f
2808 ;; find first set.
2809
2810 ;; The scan instruction searches from the most significant bit while ffs
2811 ;; searches from the least significant bit.  The bit index and treatment of
2812 ;; zero also differ.  It takes at least 7 instructions to get the proper
2813 ;; result.  Here is an obvious 8 instruction seequence.
2814
2815 (define_insn "ffssi2"
2816   [(set (match_operand:SI 0 "register_operand" "=&r")
2817         (ffs:SI (match_operand:SI 1 "register_operand" "r")))
2818    (clobber (match_scratch:SI 2 "=&r"))]
2819   "TARGET_SPARCLITE"
2820   "sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0"
2821   [(set_attr "type" "multi")
2822    (set_attr "length" "8")])
2823 \f
2824 ;; Split up troublesome insns for better scheduling.  */
2825
2826 ;; The following patterns are straightforward.  They can be applied
2827 ;; either before or after register allocation.
2828
2829 (define_split
2830   [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")])
2831         (match_operand 2 "reg_or_0_operand" ""))
2832    (clobber (match_operand:SI 3 "register_operand" ""))]
2833   "! flag_pic"
2834   [(set (match_dup 3) (high:SI (match_dup 1)))
2835    (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))])
2836         (match_dup 2))]
2837   "")
2838
2839 (define_split
2840   [(set (match_operator 0 "memop"
2841                         [(match_operand:SI 1 "immediate_operand" "")])
2842         (match_operand 2 "general_operand" ""))
2843    (clobber (match_operand:SI 3 "register_operand" ""))]
2844   "flag_pic"
2845   [(set (match_op_dup 0 [(match_dup 1)])
2846         (match_dup 2))]
2847   "
2848 {
2849   operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]),
2850                                         operands[3], 0);
2851 }")
2852
2853 (define_split
2854   [(set (match_operand 0 "register_operand" "")
2855         (match_operator 1 "memop"
2856                         [(match_operand:SI 2 "immediate_operand" "")]))]
2857   "flag_pic"
2858   [(set (match_dup 0)
2859         (match_op_dup 1 [(match_dup 2)]))]
2860   "
2861 {
2862   operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]),
2863                                         operands[0], 0);
2864 }")
2865
2866 ;; Sign- and Zero-extend operations can have symbolic memory operands.
2867
2868 (define_split
2869   [(set (match_operand 0 "register_operand" "")
2870         (match_operator 1 "extend_op"
2871                         [(match_operator 2 "memop"
2872                                          [(match_operand:SI 3 "immediate_operand" "")])]))]
2873   "flag_pic"
2874   [(set (match_dup 0)
2875         (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))]
2876   "
2877 {
2878   operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]),
2879                                         operands[0], 0);
2880 }")
2881
2882 (define_split
2883   [(set (match_operand:SI 0 "register_operand" "")
2884         (match_operand:SI 1 "immediate_operand" ""))]
2885   "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2886                   || GET_CODE (operands[1]) == CONST
2887                   || GET_CODE (operands[1]) == LABEL_REF)"
2888   [(set (match_dup 0) (high:SI (match_dup 1)))
2889    (set (match_dup 0)
2890         (lo_sum:SI (match_dup 0) (match_dup 1)))]
2891   "")
2892
2893 ;; LABEL_REFs are not modified by `legitimize_pic_address`
2894 ;; so do not recurse infinitely in the PIC case.
2895 (define_split
2896   [(set (match_operand:SI 0 "register_operand" "")
2897         (match_operand:SI 1 "immediate_operand" ""))]
2898   "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2899                 || GET_CODE (operands[1]) == CONST)"
2900   [(set (match_dup 0) (match_dup 1))]
2901   "
2902 {
2903   operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0);
2904 }")
2905 \f
2906 ;; These split sne/seq insns.  The forms of the resulting insns are 
2907 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
2908 ;; Nothing will look at these in detail after splitting has occurred.
2909
2910 (define_split
2911   [(set (match_operand:SI 0 "register_operand" "")
2912         (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2913    (clobber (reg:CC 0))]
2914   ""
2915   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2916                                          (const_int 0)))
2917    (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
2918   "")
2919
2920 (define_split
2921   [(set (match_operand:SI 0 "register_operand" "")
2922         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2923                        (const_int 0))))
2924    (clobber (reg:CC 0))]
2925   ""
2926   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2927                                          (const_int 0)))
2928    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
2929   "")
2930
2931 (define_split
2932   [(set (match_operand:SI 0 "register_operand" "")
2933         (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2934    (clobber (reg:CC 0))]
2935   ""
2936   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2937                                          (const_int 0)))
2938    (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
2939   "")
2940
2941 (define_split
2942   [(set (match_operand:SI 0 "register_operand" "")
2943         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2944                        (const_int 0))))
2945    (clobber (reg:CC 0))]
2946   ""
2947   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2948                                          (const_int 0)))
2949    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
2950   "")
2951
2952 (define_split
2953   [(set (match_operand:SI 0 "register_operand" "")
2954         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2955                         (const_int 0))
2956                  (match_operand:SI 2 "register_operand" "")))
2957    (clobber (reg:CC 0))]
2958   ""
2959   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2960                                          (const_int 0)))
2961    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
2962                                (match_dup 2)))]
2963   "")
2964
2965 (define_split
2966   [(set (match_operand:SI 0 "register_operand" "")
2967         (minus:SI (match_operand:SI 2 "register_operand" "")
2968                   (ne:SI (match_operand:SI 1 "register_operand" "")
2969                          (const_int 0))))
2970    (clobber (reg:CC 0))]
2971   ""
2972   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2973                                          (const_int 0)))
2974    (set (match_dup 0) (minus:SI (match_dup 2)
2975                                 (ltu:SI (reg:CC 0) (const_int 0))))]
2976   "")
2977
2978 (define_split
2979   [(set (match_operand:SI 0 "register_operand" "")
2980         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2981                         (const_int 0))
2982                  (match_operand:SI 2 "register_operand" "")))
2983    (clobber (reg:CC 0))]
2984   ""
2985   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2986                                          (const_int 0)))
2987    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
2988                                (match_dup 2)))]
2989   "")
2990
2991 (define_split
2992   [(set (match_operand:SI 0 "register_operand" "")
2993         (minus:SI (match_operand:SI 2 "register_operand" "")
2994                   (eq:SI (match_operand:SI 1 "register_operand" "")
2995                          (const_int 0))))
2996    (clobber (reg:CC 0))]
2997   ""
2998   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2999                                          (const_int 0)))
3000    (set (match_dup 0) (minus:SI (match_dup 2)
3001                                 (geu:SI (reg:CC 0) (const_int 0))))]
3002   "")
3003 \f
3004 ;; Peepholes go at the end.
3005
3006 ;; Optimize consecutive loads or stores into ldd and std when possible.
3007 ;; The conditions in which we do this are very restricted and are 
3008 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
3009
3010 (define_peephole
3011   [(set (match_operand:SI 0 "register_operand" "=rf")
3012         (match_operand:SI 1 "memory_operand" ""))
3013    (set (match_operand:SI 2 "register_operand" "=rf")
3014         (match_operand:SI 3 "memory_operand" ""))]
3015   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
3016    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
3017    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 
3018   "ldd %1,%0")
3019
3020 (define_peephole
3021   [(set (match_operand:SI 0 "memory_operand" "")
3022         (match_operand:SI 1 "register_operand" "rf"))
3023    (set (match_operand:SI 2 "memory_operand" "")
3024         (match_operand:SI 3 "register_operand" "rf"))]
3025   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
3026    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
3027    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
3028   "std %1,%0")
3029  
3030 (define_peephole
3031   [(set (match_operand:SF 0 "register_operand" "=fr")
3032         (match_operand:SF 1 "memory_operand" ""))
3033    (set (match_operand:SF 2 "register_operand" "=fr")
3034         (match_operand:SF 3 "memory_operand" ""))]
3035   "registers_ok_for_ldd_peep (operands[0], operands[2]) 
3036    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
3037    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
3038   "ldd %1,%0")
3039
3040 (define_peephole
3041   [(set (match_operand:SF 0 "memory_operand" "")
3042         (match_operand:SF 1 "register_operand" "fr"))
3043    (set (match_operand:SF 2 "memory_operand" "")
3044         (match_operand:SF 3 "register_operand" "fr"))]
3045   "registers_ok_for_ldd_peep (operands[1], operands[3]) 
3046    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
3047    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
3048   "std %1,%0")
3049
3050 (define_peephole
3051   [(set (match_operand:SI 0 "register_operand" "=rf")
3052         (match_operand:SI 1 "memory_operand" ""))
3053    (set (match_operand:SI 2 "register_operand" "=rf")
3054         (match_operand:SI 3 "memory_operand" ""))]
3055   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
3056    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
3057    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
3058   "ldd %3,%2")
3059
3060 (define_peephole
3061   [(set (match_operand:SI 0 "memory_operand" "")
3062         (match_operand:SI 1 "register_operand" "rf"))
3063    (set (match_operand:SI 2 "memory_operand" "")
3064         (match_operand:SI 3 "register_operand" "rf"))]
3065   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
3066    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
3067    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
3068   "std %3,%2")
3069  
3070 (define_peephole
3071   [(set (match_operand:SF 0 "register_operand" "=fr")
3072         (match_operand:SF 1 "memory_operand" ""))
3073    (set (match_operand:SF 2 "register_operand" "=fr")
3074         (match_operand:SF 3 "memory_operand" ""))]
3075   "registers_ok_for_ldd_peep (operands[2], operands[0]) 
3076    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
3077    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
3078   "ldd %3,%2")
3079
3080 (define_peephole
3081   [(set (match_operand:SF 0 "memory_operand" "")
3082         (match_operand:SF 1 "register_operand" "fr"))
3083    (set (match_operand:SF 2 "memory_operand" "")
3084         (match_operand:SF 3 "register_operand" "fr"))]
3085   "registers_ok_for_ldd_peep (operands[3], operands[1]) 
3086    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
3087    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
3088   "std %3,%2")
3089  
3090 ;; Optimize the case of following a reg-reg move with a test
3091 ;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
3092 ;; This can result from a float to fix conversion.
3093
3094 (define_peephole
3095   [(set (match_operand:SI 0 "register_operand" "=r")
3096         (match_operand:SI 1 "register_operand" "r"))
3097    (set (reg:CC 0)
3098         (compare:CC (match_operand:SI 2 "register_operand" "r")
3099                     (const_int 0)))]
3100   "(rtx_equal_p (operands[2], operands[0])
3101     || rtx_equal_p (operands[2], operands[1]))
3102    && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
3103   "orcc %1,%%g0,%0")
3104
3105 ;; Do {sign,zero}-extended compares somewhat more efficiently.
3106 ;; ??? Is this now the Right Way to do this?  Or will SCRATCH
3107 ;;     eventually have some impact here?
3108
3109 (define_peephole
3110   [(set (match_operand:HI 0 "register_operand" "")
3111         (match_operand:HI 1 "memory_operand" ""))
3112    (set (match_operand:SI 2 "register_operand" "")
3113         (sign_extend:SI (match_dup 0)))
3114    (set (reg:CC 0)
3115         (compare:CC (match_dup 2)
3116                     (const_int 0)))]
3117   ""
3118   "ldsh %1,%0\;orcc %0,%%g0,%2")
3119
3120 (define_peephole
3121   [(set (match_operand:QI 0 "register_operand" "")
3122         (match_operand:QI 1 "memory_operand" ""))
3123    (set (match_operand:SI 2 "register_operand" "")
3124         (sign_extend:SI (match_dup 0)))
3125    (set (reg:CC 0)
3126         (compare:CC (match_dup 2)
3127                     (const_int 0)))]
3128   ""
3129   "ldsb %1,%0\;orcc %0,%%g0,%2")
3130
3131 (define_peephole
3132   [(set (match_operand:HI 0 "register_operand" "")
3133         (match_operand:HI 1 "memory_operand" ""))
3134    (set (match_operand:SI 2 "register_operand" "")
3135         (sign_extend:SI (match_dup 0)))]
3136   "dead_or_set_p (insn, operands[0])"
3137   "*
3138 {
3139   warning (\"bad peephole\");
3140   if (! MEM_VOLATILE_P (operands[1]))
3141     abort ();
3142   return \"ldsh %1,%2\";
3143 }")
3144
3145 (define_peephole
3146   [(set (match_operand:QI 0 "register_operand" "")
3147         (match_operand:QI 1 "memory_operand" ""))
3148    (set (match_operand:SI 2 "register_operand" "")
3149         (sign_extend:SI (match_dup 0)))]
3150   "dead_or_set_p (insn, operands[0])"
3151   "*
3152 {
3153   warning (\"bad peephole\");
3154   if (! MEM_VOLATILE_P (operands[1]))
3155     abort ();
3156   return \"ldsb %1,%2\";
3157 }")
3158
3159 ;; Floating-point move peepholes
3160
3161 (define_peephole
3162   [(set (match_operand:SI 0 "register_operand" "=r")
3163         (lo_sum:SI (match_dup 0)
3164                    (match_operand:SI 1 "immediate_operand" "i")))
3165    (set (match_operand:DF 2 "register_operand" "=fr")
3166         (mem:DF (match_dup 0)))]
3167   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
3168   "*
3169 {
3170   /* Go by way of output_move_double in case the register in operand 2
3171      is not properly aligned for ldd.  */
3172   operands[1] = gen_rtx (MEM, DFmode,
3173                          gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
3174   operands[0] = operands[2];
3175   return output_move_double (operands);
3176 }")
3177
3178 (define_peephole
3179   [(set (match_operand:SI 0 "register_operand" "=r")
3180         (lo_sum:SI (match_dup 0)
3181                    (match_operand:SI 1 "immediate_operand" "i")))
3182    (set (match_operand:SF 2 "register_operand" "=fr")
3183         (mem:SF (match_dup 0)))]
3184   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
3185   "ld [%0+%%lo(%a1)],%2")
3186
3187 ;; Return peepholes.  First the "normal" ones
3188
3189 ;; ??? There are QImode, HImode, and SImode versions of this pattern.
3190 ;; It might be possible to write one more general pattern instead of three.
3191
3192 (define_insn ""
3193   [(set (match_operand:QI 0 "restore_operand" "")
3194         (match_operand:QI 1 "arith_operand" "rI"))
3195    (return)]
3196   "! TARGET_EPILOGUE"
3197   "*
3198 {
3199   if (current_function_returns_struct)
3200     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3201   else
3202     return \"ret\;restore %%g0,%1,%Y0\";
3203 }"
3204   [(set_attr "type" "multi")])
3205
3206 (define_insn ""
3207   [(set (match_operand:HI 0 "restore_operand" "")
3208         (match_operand:HI 1 "arith_operand" "rI"))
3209    (return)]
3210   "! TARGET_EPILOGUE"
3211   "*
3212 {
3213   if (current_function_returns_struct)
3214     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3215   else
3216     return \"ret\;restore %%g0,%1,%Y0\";
3217 }"
3218   [(set_attr "type" "multi")])
3219
3220 (define_insn ""
3221   [(set (match_operand:SI 0 "restore_operand" "")
3222         (match_operand:SI 1 "arith_operand" "rI"))
3223    (return)]
3224   "! TARGET_EPILOGUE"
3225   "*
3226 {
3227   if (current_function_returns_struct)
3228     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3229   else
3230     return \"ret\;restore %%g0,%1,%Y0\";
3231 }"
3232   [(set_attr "type" "multi")])
3233
3234 ;; The following pattern is only generated by delayed-branch scheduling,
3235 ;; when the insn winds up in the epilogue.  This can only happen when
3236 ;; ! TARGET_FPU because otherwise fp return values are in %f0.
3237 (define_insn ""
3238   [(set (match_operand:SF 0 "restore_operand" "r")
3239         (match_operand:SF 1 "register_operand" "r"))
3240    (return)]
3241   "! TARGET_FPU && ! TARGET_EPILOGUE"
3242   "*
3243 {
3244   if (current_function_returns_struct)
3245     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3246   else
3247     return \"ret\;restore %%g0,%1,%Y0\";
3248 }"
3249   [(set_attr "type" "multi")])
3250
3251 (define_insn ""
3252   [(set (match_operand:SI 0 "restore_operand" "")
3253         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3254                  (match_operand:SI 2 "arith_operand" "rI")))
3255    (return)]
3256   "! TARGET_EPILOGUE"
3257   "*
3258 {
3259   if (current_function_returns_struct)
3260     return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
3261   else
3262     return \"ret\;restore %r1,%2,%Y0\";
3263 }"
3264   [(set_attr "type" "multi")])
3265
3266 ;; Turned off because it should never match (subtracting a constant
3267 ;; is turned into addition) and because it would do the wrong thing
3268 ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
3269 ;;(define_insn ""
3270 ;;  [(set (match_operand:SI 0 "restore_operand" "")
3271 ;;      (minus:SI (match_operand:SI 1 "register_operand" "r")
3272 ;;                (match_operand:SI 2 "small_int" "I")))
3273 ;;   (return)]
3274 ;;  "! TARGET_EPILOGUE"
3275 ;;  "ret\;restore %1,-(%2),%Y0"
3276 ;;  [(set_attr "type" "multi")])
3277
3278 ;; The following pattern is only generated by delayed-branch scheduling,
3279 ;; when the insn winds up in the epilogue.
3280 (define_insn ""
3281   [(set (reg:SF 32)
3282         (match_operand:SF 0 "register_operand" "f"))
3283    (return)]
3284   "! TARGET_EPILOGUE"
3285   "ret\;fmovs %0,%%f0"
3286   [(set_attr "type" "multi")])
3287
3288 ;; Now peepholes to go a call followed by a jump.
3289
3290 (define_peephole
3291   [(parallel [(set (match_operand 0 "" "")
3292                    (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r"))
3293                          (match_operand 2 "" "")))
3294               (clobber (reg:SI 15))])
3295    (set (pc) (label_ref (match_operand 3 "" "")))]
3296   "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
3297   "*
3298 {
3299   return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
3300 }")
3301
3302 (define_peephole
3303   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
3304                     (match_operand 1 "" ""))
3305               (clobber (reg:SI 15))])
3306    (set (pc) (label_ref (match_operand 2 "" "")))]
3307   "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
3308   "*
3309 {
3310   return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
3311 }")
3312
3313 (define_peephole
3314   [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
3315                    (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
3316                              (reg:SI 0)))
3317               (clobber (reg:CC 0))])
3318    (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]
3319   ""
3320   "subxcc %r1,0,%0")
3321
3322 ;;- Local variables:
3323 ;;- mode:emacs-lisp
3324 ;;- comment-start: ";;- "
3325 ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
3326 ;;- eval: (modify-syntax-entry ?[ "(]")
3327 ;;- eval: (modify-syntax-entry ?] ")[")
3328 ;;- eval: (modify-syntax-entry ?{ "(}")
3329 ;;- eval: (modify-syntax-entry ?} "){")
3330 ;;- End: