OSDN Git Service

Initial revision
[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,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" "move,unary")
60          (if_then_else (ior (match_operand 1 "arith_operand" "")
61                             (match_operand 1 "arith_double_operand" ""))
62                        (const_int 1) (const_int 2))]
63
64         (const_int 1)))
65
66 (define_asm_attributes
67   [(set_attr "length" "1")
68    (set_attr "type" "multi")])
69
70 ;; Attributes for instruction and branch scheduling
71
72 (define_attr "in_call_delay" "false,true"
73   (cond [(eq_attr "type" "branch,call,call_no_delay_slot,multi")
74                 (const_string "false")
75          (eq_attr "type" "load,fpload,store,fpstore")
76                 (if_then_else (eq_attr "length" "1")
77                               (const_string "true")
78                               (const_string "false"))
79          (eq_attr "type" "address")
80                 (if_then_else (eq_attr "use_clobbered" "false")
81                               (const_string "true")
82                               (const_string "false"))]
83         (if_then_else (eq_attr "length" "1")
84                       (const_string "true")
85                       (const_string "false"))))
86
87 (define_delay (eq_attr "type" "call")
88   [(eq_attr "in_call_delay" "true") (nil) (nil)])
89
90 ;; ??? Should implement the notion of predelay slots for floating point
91 ;; branches.  This would allow us to remove the nop always inserted before
92 ;; a floating point branch.
93
94 (define_attr "in_branch_delay" "false,true"
95   (if_then_else (and (eq_attr "type" "!branch,call,call_no_delay_slot,multi")
96                      (eq_attr "length" "1"))
97                 (const_string "true")
98                 (const_string "false")))
99
100 (define_delay (eq_attr "type" "branch")
101   [(eq_attr "in_branch_delay" "true")
102    (nil) (eq_attr "in_branch_delay" "true")])
103
104 ;; Function units of the SPARC
105
106 ;; (define_function_unit {name} {num-units} {n-users} {test}
107 ;;                       {ready-delay} {busy-delay} [{conflict-list}])
108
109 ;; The integer ALU.
110 ;; (Noted only for documentation; units that take one cycle do not need to
111 ;; be specified.)
112
113 ;; (define_function_unit "alu" 1 0
114 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
115
116 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
117 (define_function_unit "memory" 1 0 (eq_attr "type" "load,fpload") 2 0)
118
119 ;; SPARC has two floating-point units: the FP ALU,
120 ;; and the FP MUL/DIV/SQRT unit.
121 ;; Instruction timings on the CY7C602 are as follows
122 ;; FABSs        4
123 ;; FADDs/d      5/5
124 ;; FCMPs/d      4/4
125 ;; FDIVs/d      23/37
126 ;; FMOVs        4
127 ;; FMULs/d      5/7
128 ;; FNEGs        4
129 ;; FSQRTs/d     34/63
130 ;; FSUBs/d      5/5
131 ;; FdTOi/s      5/5
132 ;; FsTOi/d      5/5
133 ;; FiTOs/d      9/5
134
135 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
136 ;; More insns cause the chip to stall.  Until we handle this
137 ;; better in the scheduler, we use excess cycle times to
138 ;; more evenly spread out fp insns.
139
140 (define_function_unit "fp_alu" 1 2 (eq_attr "type" "fp") 8 0)
141 (define_function_unit "fp_mul" 1 2 (eq_attr "type" "fpmul") 10 0)
142 (define_function_unit "fp_div" 1 2 (eq_attr "type" "fpdiv") 23 0)
143 (define_function_unit "fp_sqrt" 1 2 (eq_attr "type" "fpsqrt") 34 0)
144 \f
145 ;; Compare instructions.
146 ;; This controls RTL generation and register allocation.
147
148 ;; We generate RTL for comparisons and branches by having the cmpxx 
149 ;; patterns store away the operands.  Then, the scc and bcc patterns
150 ;; emit RTL for both the compare and the branch.
151 ;;
152 ;; We do this because we want to generate different code for an sne and
153 ;; seq insn.  In those cases, if the second operand of the compare is not
154 ;; const0_rtx, we want to compute the xor of the two operands and test
155 ;; it against zero.
156 ;;
157 ;; We start with the DEFINE_EXPANDs, then then DEFINE_INSNs to match
158 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
159 ;; insns that actually require more than one machine instruction.
160
161 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
162
163 (define_expand "cmpsi"
164   [(set (reg:CC 0)
165         (compare:CC (match_operand:SI 0 "register_operand" "")
166                     (match_operand:SI 1 "arith_operand" "")))]
167   ""
168   "
169 {
170   sparc_compare_op0 = operands[0];
171   sparc_compare_op1 = operands[1];
172   DONE;
173 }")
174
175 (define_expand "cmpsf"
176   [(set (reg:CCFP 0)
177         (compare:CCFP (match_operand:SF 0 "register_operand" "")
178                       (match_operand:SF 1 "register_operand" "")))]
179   ""
180   "
181 {
182   sparc_compare_op0 = operands[0];
183   sparc_compare_op1 = operands[1];
184   DONE;
185 }")
186
187 (define_expand "cmpdf"
188   [(set (reg:CCFP 0)
189         (compare:CCFP (match_operand:DF 0 "register_operand" "")
190                       (match_operand:DF 1 "register_operand" "")))]
191   ""
192   "
193 {
194   sparc_compare_op0 = operands[0];
195   sparc_compare_op1 = operands[1];
196   DONE;
197 }")
198
199 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
200 ;; without jumps using the addx/subx instructions.  For the rest, we do
201 ;; branches.  Seq_special and sne_special clobber the CC reg, because they
202 ;; generate addcc/subcc instructions.
203
204 (define_expand "seq_special"
205   [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
206                               (match_operand:SI 2 "register_operand" "")))
207    (parallel [(set (match_operand:SI 0 "register_operand" "")
208                    (eq:SI (match_dup 3) (const_int 0)))
209               (clobber (reg:CC 0))])]
210              
211   ""
212   "{ operands[3] = gen_reg_rtx (SImode); }")
213
214 (define_expand "sne_special"
215   [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
216                               (match_operand:SI 2 "register_operand" "")))
217    (parallel [(set (match_operand:SI 0 "register_operand" "")
218                    (ne:SI (match_dup 3) (const_int 0)))
219               (clobber (reg:CC 0))])]
220   ""
221   "{ operands[3] = gen_reg_rtx (SImode); }")
222
223 (define_expand "seq"
224   [(set (match_operand:SI 0 "register_operand" "")
225         (eq:SI (match_dup 1) (const_int 0)))]
226   ""
227   "
228 { if (GET_MODE (sparc_compare_op0) == SImode)
229     {
230       emit_insn (gen_seq_special (operands[0], sparc_compare_op0,
231                                   sparc_compare_op1));
232       DONE;
233     }
234   else
235     operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
236 }")
237
238 (define_expand "sne"
239   [(set (match_operand:SI 0 "register_operand" "")
240         (ne:SI (match_dup 1) (const_int 0)))]
241   ""
242   "
243 { if (GET_MODE (sparc_compare_op0) == SImode)
244     {
245       emit_insn (gen_sne_special (operands[0], sparc_compare_op0,
246                                   sparc_compare_op1));
247       DONE;
248     }
249   else
250     operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
251 }")
252
253 (define_expand "sgt"
254   [(set (match_operand:SI 0 "register_operand" "")
255         (gt:SI (match_dup 1) (const_int 0)))]
256   ""
257   "
258 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
259
260 (define_expand "slt"
261   [(set (match_operand:SI 0 "register_operand" "")
262         (lt:SI (match_dup 1) (const_int 0)))]
263   ""
264   "
265 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
266
267 (define_expand "sge"
268   [(set (match_operand:SI 0 "register_operand" "")
269         (ge:SI (match_dup 1) (const_int 0)))]
270   ""
271   "
272 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
273
274 (define_expand "sle"
275   [(set (match_operand:SI 0 "register_operand" "")
276         (le:SI (match_dup 1) (const_int 0)))]
277   ""
278   "
279 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
280
281 (define_expand "sgtu"
282   [(set (match_operand:SI 0 "register_operand" "")
283         (gtu:SI (match_dup 1) (const_int 0)))]
284   ""
285   "
286 {
287   rtx tem;
288
289   /* We can do ltu easily, so if both operands are registers, swap them and
290      do a LTU.  */
291   if ((GET_CODE (sparc_compare_op0) == REG
292        || GET_CODE (sparc_compare_op0) == SUBREG)
293       && (GET_CODE (sparc_compare_op1) == REG
294           || GET_CODE (sparc_compare_op1) == SUBREG))
295     {
296       tem = sparc_compare_op0;
297       sparc_compare_op0 = sparc_compare_op1;
298       sparc_compare_op1 = tem;
299       emit_insn (gen_sltu (operands[0]));
300       DONE;
301     }
302
303   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
304 }")
305
306 (define_expand "sltu"
307   [(set (match_operand:SI 0 "register_operand" "")
308         (ltu:SI (match_dup 1) (const_int 0)))]
309   ""
310   "
311 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
312 }")
313
314 (define_expand "sgeu"
315   [(set (match_operand:SI 0 "register_operand" "")
316         (geu:SI (match_dup 1) (const_int 0)))]
317   ""
318   "
319 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
320 }")
321
322 (define_expand "sleu"
323   [(set (match_operand:SI 0 "register_operand" "")
324         (leu:SI (match_dup 1) (const_int 0)))]
325   ""
326   "
327 {
328   rtx tem;
329
330   /* We can do geu easily, so if both operands are registers, swap them and
331      do a GEU.  */
332   if ((GET_CODE (sparc_compare_op0) == REG
333        || GET_CODE (sparc_compare_op0) == SUBREG)
334       && (GET_CODE (sparc_compare_op1) == REG
335           || GET_CODE (sparc_compare_op1) == SUBREG))
336     {
337       tem = sparc_compare_op0;
338       sparc_compare_op0 = sparc_compare_op1;
339       sparc_compare_op1 = tem;
340       emit_insn (gen_sgeu (operands[0]));
341       DONE;
342     }
343
344   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
345 }")
346
347 ;; Now the DEFINE_INSNs for the compare and scc cases.  First the compares.
348
349 (define_insn ""
350   [(set (reg:CC 0)
351         (compare:CC (match_operand:SI 0 "register_operand" "rJ")
352                     (match_operand:SI 1 "arith_operand" "rI")))]
353   ""
354   "cmp %r0,%1"
355   [(set_attr "type" "compare")])
356
357 (define_insn ""
358   [(set (reg:CCFP 0)
359         (compare:CCFP (match_operand:DF 0 "register_operand" "f")
360                       (match_operand:DF 1 "register_operand" "f")))]
361   ""
362   "fcmped %0,%1"
363   [(set_attr "type" "fpcmp")])
364
365 (define_insn ""
366   [(set (reg:CCFP 0)
367         (compare:CCFP (match_operand:SF 0 "register_operand" "f")
368                       (match_operand:SF 1 "register_operand" "f")))]
369   ""
370   "fcmpes %0,%1"
371   [(set_attr "type" "fpcmp")])
372
373 ;; The SEQ and SNE patterns are special because they can be done
374 ;; without any branching and do not involve a COMPARE.
375
376 (define_insn ""
377   [(set (match_operand:SI 0 "register_operand" "=r")
378         (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
379    (clobber (reg:CC 0))]
380   ""
381   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
382   [(set_attr "type" "unary")
383    (set_attr "length" "2")])
384
385 (define_insn ""
386   [(set (match_operand:SI 0 "register_operand" "=r")
387         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
388                        (const_int 0))))
389    (clobber (reg:CC 0))]
390   ""
391   "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
392   [(set_attr "type" "unary")
393    (set_attr "length" "2")])
394
395 (define_insn ""
396   [(set (match_operand:SI 0 "register_operand" "=r")
397         (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
398    (clobber (reg:CC 0))]
399   ""
400   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
401   [(set_attr "type" "unary")
402    (set_attr "length" "2")])
403
404 (define_insn ""
405   [(set (match_operand:SI 0 "register_operand" "=r")
406         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
407                        (const_int 0))))
408    (clobber (reg:CC 0))]
409   ""
410   "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
411   [(set_attr "type" "unary")
412    (set_attr "length" "2")])
413
414 ;; We can also do (x + (i == 0)) and related, so put them in.
415
416 (define_insn ""
417   [(set (match_operand:SI 0 "register_operand" "=r")
418         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
419                         (const_int 0))
420                  (match_operand:SI 2 "register_operand" "r")))
421    (clobber (reg:CC 0))]
422   ""
423   "subcc %%g0,%1,%%g0\;addx %2,0,%0"
424   [(set_attr "length" "2")])
425
426 (define_insn ""
427   [(set (match_operand:SI 0 "register_operand" "=r")
428         (minus:SI (match_operand:SI 2 "register_operand" "r")
429                   (ne:SI (match_operand:SI 1 "register_operand" "r")
430                          (const_int 0))))
431    (clobber (reg:CC 0))]
432   ""
433   "subcc %%g0,%1,%%g0\;subx %2,0,%0"
434   [(set_attr "length" "2")])
435
436 (define_insn ""
437   [(set (match_operand:SI 0 "register_operand" "=r")
438         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
439                         (const_int 0))
440                  (match_operand:SI 2 "register_operand" "r")))
441    (clobber (reg:CC 0))]
442   ""
443   "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
444   [(set_attr "length" "2")])
445
446 (define_insn ""
447   [(set (match_operand:SI 0 "register_operand" "=r")
448         (minus:SI (match_operand:SI 2 "register_operand" "r")
449                   (eq:SI (match_operand:SI 1 "register_operand" "r")
450                          (const_int 0))))
451    (clobber (reg:CC 0))]
452   ""
453   "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
454   [(set_attr "type" "unary")
455    (set_attr "length" "2")])
456
457 ;; We can also do GEU and LTU directly, but these operate after a
458 ;; compare.
459
460 (define_insn ""
461   [(set (match_operand:SI 0 "register_operand" "=r")
462         (ltu:SI (reg:CC 0) (const_int 0)))]
463   ""
464   "addx %%g0,0,%0"
465   [(set_attr "type" "misc")])
466
467 (define_insn ""
468   [(set (match_operand:SI 0 "register_operand" "=r")
469         (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
470   ""
471   "subx %%g0,0,%0"
472   [(set_attr "type" "misc")])
473
474 ;; ??? Combine should canonicalize these next two to the same pattern.
475 (define_insn ""
476   [(set (match_operand:SI 0 "register_operand" "=r")
477         (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0)))
478                   (match_operand:SI 1 "arith_operand" "rI")))]
479   ""
480   "subx %%g0,%1,%0"
481   [(set_attr "type" "unary")])
482
483 (define_insn ""
484   [(set (match_operand:SI 0 "register_operand" "=r")
485         (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
486                          (match_operand:SI 1 "arith_operand" "rI"))))]
487   ""
488   "subx %%g0,%1,%0"
489   [(set_attr "type" "unary")])
490
491 (define_insn ""
492   [(set (match_operand:SI 0 "register_operand" "=r")
493         (geu:SI (reg:CC 0) (const_int 0)))]
494   ""
495   "subx %%g0,-1,%0"
496   [(set_attr "type" "misc")])
497
498 (define_insn ""
499   [(set (match_operand:SI 0 "register_operand" "=r")
500         (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
501   ""
502   "addx %%g0,-1,%0"
503   [(set_attr "type" "misc")])
504
505 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
506
507 (define_insn ""
508   [(set (match_operand:SI 0 "register_operand" "=r")
509         (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
510                  (match_operand:SI 1 "arith_operand" "rI")))]
511   ""
512   "addx %%g0,%1,%0"
513   [(set_attr "type" "unary")])
514
515 (define_insn ""
516   [(set (match_operand:SI 0 "register_operand" "=r")
517         (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
518                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
519                           (match_operand:SI 2 "arith_operand" "rI"))))]
520   ""
521   "addx %1,%2,%0"
522   [(set_attr "type" "binary")])
523
524 (define_insn ""
525   [(set (match_operand:SI 0 "register_operand" "=r")
526         (minus:SI (match_operand:SI 1 "register_operand" "r")
527                   (ltu:SI (reg:CC 0) (const_int 0))))]
528   ""
529   "subx %1,0,%0"
530   [(set_attr "type" "unary")])
531
532 ;; ??? Combine should canonicalize these next two to the same pattern.
533 (define_insn ""
534   [(set (match_operand:SI 0 "register_operand" "=r")
535         (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
536                             (match_operand:SI 2 "arith_operand" "rI"))
537                   (ltu:SI (reg:CC 0) (const_int 0))))]
538   ""
539   "subx %1,%2,%0"
540   [(set_attr "type" "binary")])
541
542 (define_insn ""
543   [(set (match_operand:SI 0 "register_operand" "=r")
544         (minus:SI (match_operand:SI 1 "register_operand" "r")
545                   (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
546                            (match_operand:SI 2 "arith_operand" "rI"))))]
547   ""
548   "subx %1,%2,%0"
549   [(set_attr "type" "binary")])
550
551 (define_insn ""
552   [(set (match_operand:SI 0 "register_operand" "=r")
553         (plus:SI (geu:SI (reg:CC 0) (const_int 0))
554                  (match_operand:SI 1 "register_operand" "r")))]
555   ""
556   "subx %1,-1,%0"
557   [(set_attr "type" "unary")])
558
559 (define_insn ""
560   [(set (match_operand:SI 0 "register_operand" "=r")
561         (minus:SI (match_operand:SI 1 "register_operand" "r")
562                   (geu:SI (reg:CC 0) (const_int 0))))]
563   ""
564   "addx %1,-1,%0"
565   [(set_attr "type" "unary")])
566
567 ;; Now we have the generic scc insns.  These will be done using a jump.
568 ;; We have to exclude the cases above, since we will not want combine to
569 ;; turn something that does not require a jump into something that does.
570 (define_insn ""
571   [(set (match_operand:SI 0 "register_operand" "=r")
572         (match_operator:SI 1 "normal_comp_operator" [(reg 0) (const_int 0)]))]
573   ""
574   "* return output_scc_insn (operands, insn); "
575   [(set_attr "type" "multi")])
576 \f
577 ;; These control RTL generation for conditional jump insns
578
579 (define_expand "beq"
580   [(set (pc)
581         (if_then_else (eq (match_dup 1) (const_int 0))
582                       (label_ref (match_operand 0 "" ""))
583                       (pc)))]
584   ""
585   "
586 { operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); }")
587
588 (define_expand "bne"
589   [(set (pc)
590         (if_then_else (ne (match_dup 1) (const_int 0))
591                       (label_ref (match_operand 0 "" ""))
592                       (pc)))]
593   ""
594   "
595 { operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); }")
596
597 (define_expand "bgt"
598   [(set (pc)
599         (if_then_else (gt (match_dup 1) (const_int 0))
600                       (label_ref (match_operand 0 "" ""))
601                       (pc)))]
602   ""
603   "
604 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
605
606 (define_expand "bgtu"
607   [(set (pc)
608         (if_then_else (gtu (match_dup 1) (const_int 0))
609                       (label_ref (match_operand 0 "" ""))
610                       (pc)))]
611   ""
612   "
613 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
614 }")
615
616 (define_expand "blt"
617   [(set (pc)
618         (if_then_else (lt (match_dup 1) (const_int 0))
619                       (label_ref (match_operand 0 "" ""))
620                       (pc)))]
621   ""
622   "
623 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
624
625 (define_expand "bltu"
626   [(set (pc)
627         (if_then_else (ltu (match_dup 1) (const_int 0))
628                       (label_ref (match_operand 0 "" ""))
629                       (pc)))]
630   ""
631   "
632 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
633 }")
634
635 (define_expand "bge"
636   [(set (pc)
637         (if_then_else (ge (match_dup 1) (const_int 0))
638                       (label_ref (match_operand 0 "" ""))
639                       (pc)))]
640   ""
641   "
642 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
643
644 (define_expand "bgeu"
645   [(set (pc)
646         (if_then_else (geu (match_dup 1) (const_int 0))
647                       (label_ref (match_operand 0 "" ""))
648                       (pc)))]
649   ""
650   "
651 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
652 }")
653
654 (define_expand "ble"
655   [(set (pc)
656         (if_then_else (le (match_dup 1) (const_int 0))
657                       (label_ref (match_operand 0 "" ""))
658                       (pc)))]
659   ""
660   "
661 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
662
663 (define_expand "bleu"
664   [(set (pc)
665         (if_then_else (leu (match_dup 1) (const_int 0))
666                       (label_ref (match_operand 0 "" ""))
667                       (pc)))]
668   ""
669   "
670 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
671 }")
672 \f
673 ;; Now match both normal and inverted jump.
674
675 (define_insn ""
676   [(set (pc)
677         (if_then_else (match_operator 0 "noov_compare_op"
678                                       [(reg 0) (const_int 0)])
679                       (label_ref (match_operand 1 "" ""))
680                       (pc)))]
681   ""
682   "*
683 {
684   return output_cbranch (operands[0], 1, 0,
685                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
686                          ! final_sequence);
687 }"
688   [(set_attr "type" "branch")])
689
690 (define_insn ""
691   [(set (pc)
692         (if_then_else (match_operator 0 "noov_compare_op"
693                                       [(reg 0) (const_int 0)])
694                       (pc)
695                       (label_ref (match_operand 1 "" ""))))]
696   ""
697   "*
698 {
699   return output_cbranch (operands[0], 1, 1,
700                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
701                          ! final_sequence);
702 }"
703   [(set_attr "type" "branch")])
704 \f
705 ;; Move instructions
706
707 (define_expand "movsi"
708   [(set (match_operand:SI 0 "general_operand" "")
709         (match_operand:SI 1 "general_operand" ""))]
710   ""
711   "
712 {
713   if (emit_move_sequence (operands, SImode, 0))
714     DONE;
715 }")
716
717 (define_expand "reload_insi"
718   [(set (match_operand:SI 0 "register_operand" "=r")
719         (match_operand:SI 1 "general_operand" ""))
720    (clobber (match_operand:SI 2 "register_operand" "=&r"))]
721   ""
722   "
723 {
724   if (emit_move_sequence (operands, SImode, operands[2]))
725     DONE;
726
727   /* We don't want the clobber emitted, so handle this ourselves.  */
728   emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
729   DONE;
730 }")
731
732 ;; We must support both 'r' and 'f' registers here, because combine may
733 ;; convert SFmode hard registers to SImode hard registers when simplifying
734 ;; subreg sets.
735
736 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
737 ;; problems with register allocation.  Reload might try to put an interger
738 ;; in an fp register, or an fp number is an integer register.
739
740 (define_insn ""
741   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,Q,Q,rf")
742         (match_operand:SI 1 "move_operand" "rI,K,Q,!Q,rJ,!f,!fr"))]
743   "register_operand (operands[0], SImode)
744    || register_operand (operands[1], SImode)
745    || operands[1] == const0_rtx"
746   "@
747    mov %1,%0
748    sethi %%hi(%a1),%0
749    ld %1,%0
750    ld %1,%0
751    st %r1,%0
752    st %r1,%0
753    st %r1,[%%fp-4]\;ld [%%fp-4],%0"
754   [(set_attr "type" "move,move,load,load,store,store,misc")
755    (set_attr "length" "*,1,*,*,*,*,2")])
756
757 ;; Special pic pattern, for loading the address of a label into a register.
758 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
759 ;; there.
760
761 (define_insn ""
762   [(set (match_operand:SI 0 "register_operand" "=r")
763         (match_operand:SI 1 "move_pic_label" "i"))
764    (set (reg:SI 15) (pc))]
765   ""
766   "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
767   [(set_attr "type" "multi")
768    (set_attr "length" "4")])
769
770 (define_insn ""
771   [(set (match_operand:DI 0 "register_operand" "=r")
772         (high:DI (match_operand 1 "" "")))]
773   "check_pic (1)"
774   "*
775 {
776   rtx op0 = operands[0];
777   rtx op1 = operands[1];
778
779   if (GET_CODE (op1) == CONST_INT)
780     {
781       operands[0] = operand_subword (op0, 1, 0, DImode);
782       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
783
784       operands[0] = operand_subword (op0, 0, 0, DImode);
785       if (INTVAL (op1) < 0)
786         output_asm_insn (\"mov -1,%0\", operands);
787       else
788         output_asm_insn (\"mov 0,%0\", operands);
789     }
790   else if (GET_CODE (op1) == CONST_DOUBLE)
791     {
792       operands[0] = operand_subword (op0, 1, 0, DImode);
793       operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
794       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
795
796       operands[0] = operand_subword (op0, 0, 0, DImode);
797       operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
798       output_asm_insn (singlemove_string (operands), operands);
799     }
800   else
801     abort ();
802 }"
803   [(set_attr "type" "move")
804    (set_attr "length" "2")])
805
806 (define_insn ""
807   [(set (match_operand:SI 0 "register_operand" "=r")
808         (high:SI (match_operand 1 "" "")))]
809   "check_pic (1)"
810   "sethi %%hi(%a1),%0"
811   [(set_attr "type" "move")
812    (set_attr "length" "1")])
813
814 (define_insn ""
815   [(set (match_operand:HI 0 "register_operand" "=r")
816         (high:HI (match_operand 1 "" "")))]
817   "check_pic (1)"
818   "sethi %%hi(%a1),%0"
819   [(set_attr "type" "move")
820    (set_attr "length" "1")])
821
822 (define_insn ""
823   [(set (match_operand:DI 0 "register_operand" "=r")
824         (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
825                    (match_operand:DI 2 "immediate_operand" "in")))]
826   ""
827   "or %R1,%%lo(%a2),%R0"
828   ;; Need to set length for this arith insn because operand2
829   ;; is not an "arith_operand".
830   [(set_attr "length" "1")])
831
832 (define_insn ""
833   [(set (match_operand:SI 0 "register_operand" "=r")
834         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
835                    (match_operand:SI 2 "immediate_operand" "in")))]
836   ""
837   "or %1,%%lo(%a2),%0"
838   ;; Need to set length for this arith insn because operand2
839   ;; is not an "arith_operand".
840   [(set_attr "length" "1")])
841
842 (define_insn ""
843   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
844         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
845    (clobber (match_scratch:SI 2 "=&r"))]
846   ""
847   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
848   [(set_attr "type" "store")
849    (set_attr "length" "2")])
850
851 (define_expand "movhi"
852   [(set (match_operand:HI 0 "general_operand" "")
853         (match_operand:HI 1 "general_operand" ""))]
854   ""
855   "
856 {
857   if (emit_move_sequence (operands, HImode, 0))
858     DONE;
859 }")
860
861 (define_insn ""
862   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
863         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
864   "register_operand (operands[0], HImode)
865    || register_operand (operands[1], HImode)
866    || operands[1] == const0_rtx"
867   "@
868    mov %1,%0
869    sethi %%hi(%a1),%0
870    lduh %1,%0
871    sth %r1,%0"
872   [(set_attr "type" "move,move,load,store")
873    (set_attr "length" "*,1,*,1")])
874
875 (define_insn ""
876   [(set (match_operand:HI 0 "register_operand" "=r")
877         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
878                    (match_operand 2 "immediate_operand" "in")))]
879   ""
880   "or %1,%%lo(%a2),%0"
881   [(set_attr "length" "1")])
882
883 (define_insn ""
884   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
885         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
886    (clobber (match_scratch:SI 2 "=&r"))]
887   ""
888   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
889   [(set_attr "type" "store")
890    (set_attr "length" "2")])
891
892 (define_expand "movqi"
893   [(set (match_operand:QI 0 "general_operand" "")
894         (match_operand:QI 1 "general_operand" ""))]
895   ""
896   "
897 {
898   if (emit_move_sequence (operands, QImode, 0))
899     DONE;
900 }")
901
902 (define_insn ""
903   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
904         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
905   "register_operand (operands[0], QImode)
906    || register_operand (operands[1], QImode)
907    || operands[1] == const0_rtx"
908   "@
909    mov %1,%0
910    sethi %%hi(%a1),%0
911    ldub %1,%0
912    stb %r1,%0"
913   [(set_attr "type" "move,move,load,store")
914    (set_attr "length" "*,1,*,1")])
915
916 (define_insn ""
917   [(set (match_operand:QI 0 "register_operand" "=r")
918         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
919                               (match_operand 2 "immediate_operand" "in")) 0))]
920   ""
921   "or %1,%%lo(%a2),%0"
922   [(set_attr "length" "1")])
923
924 (define_insn ""
925   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
926         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
927    (clobber (match_scratch:SI 2 "=&r"))]
928   ""
929   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
930   [(set_attr "type" "store")
931    (set_attr "length" "2")])
932
933 ;; The definition of this insn does not really explain what it does,
934 ;; but it should suffice
935 ;; that anything generated as this insn will be recognized as one
936 ;; and that it will not successfully combine with anything.
937 (define_expand "movstrsi"
938   [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
939                    (mem:BLK (match_operand:BLK 1 "general_operand" "")))
940               (use (match_operand:SI 2 "arith32_operand" ""))
941               (use (match_operand:SI 3 "immediate_operand" ""))
942               (clobber (match_dup 0))
943               (clobber (match_dup 1))
944               (clobber (match_scratch:SI 4 ""))
945               (clobber (reg:SI 0))
946               (clobber (reg:SI 1))])]
947   ""
948   "
949 {
950   if (GET_CODE (operands[2]) == CONST_INT
951       && GET_CODE (operands[3]) == CONST_INT
952       && INTVAL (operands[2]) / INTVAL (operands[3]) > 32)
953     FAIL;
954
955   operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
956   operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
957   operands[2] = force_not_mem (operands[2]);
958 }")
959
960 (define_insn ""
961   [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
962         (mem:BLK (match_operand:SI 1 "register_operand" "r")))
963    (use (match_operand:SI 2 "arith32_operand" "rn"))
964    (use (match_operand:SI 3 "immediate_operand" "i"))
965    (clobber (match_dup 0))
966    (clobber (match_dup 1))
967    (clobber (match_scratch:SI 4 "=&r"))
968    (clobber (reg:SI 0))
969    (clobber (reg:SI 1))]
970   ""
971   "* return output_block_move (operands);"
972   [(set_attr "type" "multi")])
973 \f
974 ;; Floating point move insns
975
976 ;; This pattern forces (set (reg:DF ...) (const_double ...))
977 ;; to be reloaded by putting the constant into memory.
978 ;; It must come before the more general movdf pattern.
979 ;; ??? A similar pattern for SF mode values would also be useful, but it
980 ;; is not as easy to write.
981 (define_insn ""
982   [(set (match_operand:DF 0 "general_operand" "=?r,r,f,o")
983         (match_operand:DF 1 "" "?E,G,m,G"))]
984   "GET_CODE (operands[1]) == CONST_DOUBLE"
985   "*
986 {
987   switch (which_alternative)
988     {
989     case 0:
990       return output_move_double (operands);
991     case 1:
992       return \"mov %%g0,%0\;mov %%g0,%R0\";
993     case 2:
994       return output_fp_move_double (operands);
995     case 3:
996       operands[1] = adj_offsettable_operand (operands[0], 4);
997       return \"st %%g0,%0\;st %%g0,%1\";
998     }
999 }"
1000   [(set_attr "type" "load,move,fpload,store")
1001    (set_attr "length" "3,2,3,3")])
1002
1003 (define_expand "movdf"
1004   [(set (match_operand:DF 0 "general_operand" "")
1005         (match_operand:DF 1 "general_operand" ""))]
1006   ""
1007   "
1008 {
1009   if (emit_move_sequence (operands, DFmode, 0))
1010     DONE;
1011 }")
1012
1013 (define_insn ""
1014   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r,?f,?r")
1015         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q,r,f"))]
1016   "register_operand (operands[0], DFmode)
1017    || register_operand (operands[1], DFmode)"
1018   "*
1019 {
1020   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1021     return output_fp_move_double (operands);
1022   return output_move_double (operands);
1023 }"
1024   [(set_attr "type" "fp,move,fpstore,store,fpload,load,multi,multi")
1025    (set_attr "length" "2,2,3,3,3,3,3,3")])
1026
1027 (define_insn ""
1028   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
1029         (match_operand:DF 1 "reg_or_0_operand" "rf,G"))
1030    (clobber (match_scratch:SI 2 "=&r,&r"))]
1031   ""
1032   "*
1033 {
1034   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1035   if (which_alternative == 0)
1036     return \"std %1,[%2+%%lo(%a0)]\";
1037   else
1038     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
1039 }"
1040   [(set_attr "type" "store")
1041    (set_attr "length" "3")])
1042 \f
1043 ;; Double-word move insns.
1044
1045 (define_expand "movdi"
1046   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1047         (match_operand:DI 1 "general_operand" ""))]
1048   ""
1049   "
1050 {
1051   if (emit_move_sequence (operands, DImode, 0))
1052     DONE;
1053 }")
1054
1055 (define_insn ""
1056   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?f,?r,?Q")
1057         (match_operand:DI 1 "general_operand" "r,r,Q,i,r,f,Q,f,f"))]
1058   "register_operand (operands[0], DImode)
1059    || register_operand (operands[1], DImode)
1060    || operands[1] == const0_rtx"
1061   "*
1062 {
1063   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1064     return output_fp_move_double (operands);
1065   return output_move_double (operands);
1066 }"
1067   [(set_attr "type" "move,store,load,misc,multi,fp,fpload,multi,fpstore")
1068    (set_attr "length" "2,3,3,3,3,2,3,3,3")])
1069
1070 ;; Floating-point move insns.
1071
1072 (define_expand "movsf"
1073   [(set (match_operand:SF 0 "general_operand" "")
1074         (match_operand:SF 1 "general_operand" ""))]
1075   ""
1076   "
1077 {
1078   if (emit_move_sequence (operands, SFmode, 0))
1079     DONE;
1080 }")
1081
1082 (define_insn ""
1083   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,rf,f,r,Q,Q")
1084         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,!rf,Q,Q,f,r"))]
1085   "register_operand (operands[0], SFmode)
1086    || register_operand (operands[1], SFmode)"
1087   "@
1088    fmovs %1,%0
1089    mov %1,%0
1090    st %r1,[%%fp-4]\;ld [%%fp-4],%0
1091    ld %1,%0
1092    ld %1,%0
1093    st %r1,%0
1094    st %r1,%0"
1095   [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store")
1096    (set_attr "length" "*,*,2,*,*,*,*")])
1097
1098 (define_insn ""
1099   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
1100         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
1101    (clobber (match_scratch:SI 2 "=&r"))]
1102   ""
1103   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1104   [(set_attr "type" "store")
1105    (set_attr "length" "2")])
1106 \f
1107 ;;- zero extension instructions
1108
1109 ;; These patterns originally accepted general_operands, however, slightly
1110 ;; better code is generated by only accepting register_operands, and then
1111 ;; letting combine generate the ldu[hb] insns.
1112
1113 (define_expand "zero_extendhisi2"
1114   [(set (match_operand:SI 0 "register_operand" "")
1115         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
1116   ""
1117   "
1118 {
1119   rtx temp = gen_reg_rtx (SImode);
1120   rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1121
1122   if (GET_CODE (operand1) == SUBREG)
1123     operand1 = XEXP (operand1, 0);
1124
1125   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1126                           shift_16));
1127   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
1128   DONE;
1129 }")
1130
1131 (define_insn ""
1132   [(set (match_operand:SI 0 "register_operand" "=r")
1133         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1134   ""
1135   "lduh %1,%0"
1136   [(set_attr "type" "load")])
1137
1138 (define_expand "zero_extendqihi2"
1139   [(set (match_operand:HI 0 "register_operand" "")
1140         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1141   ""
1142   "")
1143
1144 (define_insn ""
1145   [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1146         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1147   "GET_CODE (operands[1]) != CONST_INT"
1148   "@
1149    and %1,0xff,%0;
1150    mov (%1 & 0xff),%0
1151    ldub %1,%0"
1152   [(set_attr "type" "unary,move,load")
1153    (set_attr "length" "1")])
1154
1155 (define_expand "zero_extendqisi2"
1156   [(set (match_operand:SI 0 "register_operand" "")
1157         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1158   ""
1159   "")
1160
1161 (define_insn ""
1162   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1163         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1164   "GET_CODE (operands[1]) != CONST_INT"
1165   "@
1166    and %1,0xff,%0
1167    mov (%1 & 0xff),%0
1168    ldub %1,%0"
1169   [(set_attr "type" "unary,move,load")
1170    (set_attr "length" "1")])
1171
1172 (define_insn ""
1173   [(set (reg:CC 0)
1174         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
1175                     (const_int 0)))]
1176   ""
1177   "andcc %0,0xff,%%g0"
1178   [(set_attr "type" "compare")])
1179
1180 (define_insn ""
1181   [(set (reg:CC 0)
1182         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1183                     (const_int 0)))
1184    (set (match_operand:SI 0 "register_operand" "=r")
1185         (zero_extend:SI (match_dup 1)))]
1186   ""
1187   "andcc %1,0xff,%0"
1188   [(set_attr "type" "unary")])
1189 \f
1190 ;;- sign extension instructions
1191
1192 ;; These patterns originally accepted general_operands, however, slightly
1193 ;; better code is generated by only accepting register_operands, and then
1194 ;; letting combine generate the lds[hb] insns.
1195
1196 (define_expand "extendhisi2"
1197   [(set (match_operand:SI 0 "register_operand" "")
1198         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1199   ""
1200   "
1201 {
1202   rtx temp = gen_reg_rtx (SImode);
1203   rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1204
1205   if (GET_CODE (operand1) == SUBREG)
1206     operand1 = XEXP (operand1, 0);
1207
1208   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1209                           shift_16));
1210   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
1211   DONE;
1212 }")
1213
1214 (define_insn ""
1215   [(set (match_operand:SI 0 "register_operand" "=r")
1216         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1217   ""
1218   "ldsh %1,%0"
1219   [(set_attr "type" "load")])
1220
1221 (define_expand "extendqihi2"
1222   [(set (match_operand:HI 0 "register_operand" "")
1223         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
1224   ""
1225   "
1226 {
1227   rtx temp = gen_reg_rtx (SImode);
1228   rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1229
1230   if (GET_CODE (operand1) == SUBREG)
1231     operand1 = XEXP (operand1, 0);
1232   if (GET_CODE (operand0) == SUBREG)
1233     operand0 = XEXP (operand0, 0);
1234   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1235                           shift_24));
1236   if (GET_MODE (operand0) != SImode)
1237     operand0 = gen_rtx (SUBREG, SImode, operand0, 0);
1238   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1239   DONE;
1240 }")
1241
1242 (define_insn ""
1243   [(set (match_operand:HI 0 "register_operand" "=r")
1244         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
1245   ""
1246   "ldsb %1,%0"
1247   [(set_attr "type" "load")])
1248
1249 (define_expand "extendqisi2"
1250   [(set (match_operand:SI 0 "register_operand" "")
1251         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
1252   ""
1253   "
1254 {
1255   rtx temp = gen_reg_rtx (SImode);
1256   rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1257
1258   if (GET_CODE (operand1) == SUBREG)
1259     operand1 = XEXP (operand1, 0);
1260   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1261                           shift_24));
1262   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1263   DONE;
1264 }")
1265
1266 (define_insn ""
1267   [(set (match_operand:SI 0 "register_operand" "=r")
1268         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1269   ""
1270   "ldsb %1,%0"
1271   [(set_attr "type" "load")])
1272 \f
1273 ;; Conversions between float and double.
1274
1275 (define_insn "extendsfdf2"
1276   [(set (match_operand:DF 0 "register_operand" "=f")
1277         (float_extend:DF
1278          (match_operand:SF 1 "register_operand" "f")))]
1279   ""
1280   "fstod %1,%0"
1281   [(set_attr "type" "fp")])
1282
1283 (define_insn "truncdfsf2"
1284   [(set (match_operand:SF 0 "register_operand" "=f")
1285         (float_truncate:SF
1286          (match_operand:DF 1 "register_operand" "f")))]
1287   ""
1288   "fdtos %1,%0"
1289   [(set_attr "type" "fp")])
1290 \f
1291 ;; Conversion between fixed point and floating point.
1292
1293 (define_insn "floatsisf2"
1294   [(set (match_operand:SF 0 "general_operand" "=f")
1295         (float:SF (match_operand:SI 1 "nonimmediate_operand" "rfm")))]
1296   ""
1297   "* return output_floatsisf2 (operands);"
1298   [(set_attr "type" "fp")
1299    (set_attr "length" "3")])
1300
1301 (define_insn "floatsidf2"
1302   [(set (match_operand:DF 0 "general_operand" "=f")
1303         (float:DF (match_operand:SI 1 "nonimmediate_operand" "rfm")))]
1304   ""
1305   "* return output_floatsidf2 (operands);"
1306   [(set_attr "type" "fp")
1307    (set_attr "length" "3")])
1308
1309 ;; Convert a float to an actual integer.
1310 ;; Truncation is performed as part of the conversion.
1311
1312 (define_insn "fix_truncsfsi2"
1313   [(set (match_operand:SI 0 "general_operand" "=rm")
1314         (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))
1315    (clobber (match_scratch:SF 2 "=&f"))]
1316   ""
1317   "*
1318 {
1319   if (FP_REG_P (operands[1]))
1320     output_asm_insn (\"fstoi %1,%2\", operands);
1321   else
1322     output_asm_insn (\"ld %1,%2\;fstoi %2,%2\", operands);
1323   if (GET_CODE (operands[0]) == MEM)
1324     return \"st %2,%0\";
1325   else
1326     return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\";
1327 }"
1328   [(set_attr "type" "fp")
1329    (set_attr "length" "3")])
1330
1331 (define_insn "fix_truncdfsi2"
1332   [(set (match_operand:SI 0 "general_operand" "=rm")
1333         (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))
1334    (clobber (match_scratch:DF 2 "=&f"))]
1335   ""
1336   "*
1337 {
1338   if (FP_REG_P (operands[1]))
1339     output_asm_insn (\"fdtoi %1,%2\", operands);
1340   else
1341     {
1342       rtx xoperands[3];
1343       xoperands[0] = operands[2];
1344       xoperands[1] = operands[1];
1345       output_asm_insn (output_fp_move_double (xoperands), xoperands);
1346       output_asm_insn (\"fdtoi %2,%2\", operands);
1347     }
1348   if (GET_CODE (operands[0]) == MEM)
1349     return \"st %2,%0\";
1350   else
1351     return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\";
1352 }"
1353   [(set_attr "type" "fp")
1354    (set_attr "length" "3")])
1355 \f
1356 ;;- arithmetic instructions
1357
1358 (define_insn "adddi3"
1359   [(set (match_operand:DI 0 "register_operand" "=r")
1360         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
1361                  (match_operand:DI 2 "arith_double_operand" "rHI")))
1362    (clobber (reg:SI 0))]
1363   ""
1364   "*
1365 {
1366   rtx op2 = operands[2];
1367
1368   /* If constant is postive, upper bits zeroed, otherwise unchanged
1369    * give the assembler a chance to pick the move instruction. */
1370   if (GET_CODE (op2) == CONST_INT)
1371     {
1372       int sign = INTVAL (op2);
1373       if (sign < 0)
1374         return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1375       return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1376     }
1377   else if (GET_CODE (op2) == CONST_DOUBLE)
1378     {
1379       int sign = CONST_DOUBLE_HIGH (op2);
1380       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1381                              CONST_DOUBLE_LOW (operands[1]));
1382       if (sign < 0)
1383         return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1384       return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1385     }
1386   return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
1387 }"
1388   [(set_attr "length" "2")])
1389
1390 (define_insn "addsi3"
1391   [(set (match_operand:SI 0 "register_operand" "=r")
1392         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1393                  (match_operand:SI 2 "arith_operand" "rI")))]
1394   ""
1395   "add %1,%2,%0")
1396
1397 (define_insn ""
1398   [(set (reg:CC_NOOV 0)
1399         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
1400                                   (match_operand:SI 1 "arith_operand" "rI"))
1401                          (const_int 0)))]
1402   ""
1403   "addcc %0,%1,%%g0"
1404   [(set_attr "type" "compare")])
1405
1406 (define_insn ""
1407   [(set (reg:CC_NOOV 0)
1408         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1409                                   (match_operand:SI 2 "arith_operand" "rI"))
1410                          (const_int 0)))
1411    (set (match_operand:SI 0 "register_operand" "=r")
1412         (plus:SI (match_dup 1) (match_dup 2)))]
1413   ""
1414   "addcc %1,%2,%0")
1415
1416 (define_insn "subdi3"
1417   [(set (match_operand:DI 0 "register_operand" "=r")
1418         (minus:DI (match_operand:DI 1 "register_operand" "r")
1419                   (match_operand:DI 2 "arith_double_operand" "rHI")))
1420    (clobber (reg:SI 0))]
1421   ""
1422   "*
1423 {
1424   rtx op2 = operands[2];
1425
1426   /* If constant is postive, upper bits zeroed, otherwise unchanged
1427    * give the assembler a chance to pick the move instruction. */
1428   if (GET_CODE (op2) == CONST_INT)
1429     {
1430       int sign = INTVAL (op2);
1431       if (sign < 0)
1432         return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1433       return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1434     }
1435   else if (GET_CODE (op2) == CONST_DOUBLE)
1436     {
1437       int sign = CONST_DOUBLE_HIGH (op2);
1438       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1439                              CONST_DOUBLE_LOW (operands[1]));
1440       if (sign < 0)
1441         return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1442       return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1443     }
1444   return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
1445 }"
1446   [(set_attr "length" "2")])
1447
1448 (define_insn "subsi3"
1449   [(set (match_operand:SI 0 "register_operand" "=r")
1450         (minus:SI (match_operand:SI 1 "register_operand" "r")
1451                   (match_operand:SI 2 "arith_operand" "rI")))]
1452   ""
1453   "sub %1,%2,%0")
1454
1455 (define_insn ""
1456   [(set (reg:CC_NOOV 0)
1457         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
1458                                    (match_operand:SI 1 "arith_operand" "rI"))
1459                          (const_int 0)))]
1460   ""
1461   "subcc %0,%1,%%g0"
1462   [(set_attr "type" "compare")])
1463
1464 (define_insn ""
1465   [(set (reg:CC_NOOV 0)
1466         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
1467                                    (match_operand:SI 2 "arith_operand" "rI"))
1468                          (const_int 0)))
1469    (set (match_operand:SI 0 "register_operand" "=r")
1470         (minus:SI (match_dup 1) (match_dup 2)))]
1471   ""
1472   "subcc %1,%2,%0")
1473
1474 ;;- and instructions
1475 ;; We define DImode `and` so with DImode `not` we can get
1476 ;; DImode `andn`.  Other combinations are possible.
1477
1478 (define_expand "anddi3"
1479   [(set (match_operand:DI 0 "register_operand" "")
1480         (and:DI (match_operand:DI 1 "arith_double_operand" "")
1481                 (match_operand:DI 2 "arith_double_operand" "")))]
1482   ""
1483   "")
1484
1485 (define_insn ""
1486   [(set (match_operand:DI 0 "register_operand" "=r")
1487         (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
1488                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1489   ""
1490   "*
1491 {
1492   rtx op2 = operands[2];
1493
1494   /* If constant is postive, upper bits zeroed, otherwise unchanged
1495    * give the assembler a chance to pick the move instruction. */
1496   if (GET_CODE (op2) == CONST_INT)
1497     {
1498       int sign = INTVAL (op2);
1499       if (sign < 0)
1500         return \"mov %1,%0\;and %R1,%2,%R0\";
1501       return \"mov 0,%0\;and %R1,%2,%R0\";
1502     }
1503   else if (GET_CODE (op2) == CONST_DOUBLE)
1504     {
1505       int sign = CONST_DOUBLE_HIGH (op2);
1506       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1507                              CONST_DOUBLE_LOW (operands[1]));
1508       if (sign < 0)
1509         return \"mov %1,%0\;and %R1,%2,%R0\";
1510       return \"mov 0,%0\;and %R1,%2,%R0\";
1511     }
1512   return \"and %1,%2,%0\;and %R1,%R2,%R0\";
1513 }"
1514   [(set_attr "length" "2")])
1515
1516 (define_insn "andsi3"
1517   [(set (match_operand:SI 0 "register_operand" "=r")
1518         (and:SI (match_operand:SI 1 "arith_operand" "%r")
1519                 (match_operand:SI 2 "arith_operand" "rI")))]
1520   ""
1521   "and %1,%2,%0")
1522
1523 (define_insn ""
1524   [(set (match_operand:DI 0 "register_operand" "=r")
1525         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1526                 (match_operand:DI 2 "register_operand" "r")))]
1527   ""
1528   "andn %2,%1,%0\;andn %R2,%R1,%R0"
1529   [(set_attr "length" "2")])
1530
1531 (define_insn ""
1532   [(set (match_operand:SI 0 "register_operand" "=r")
1533         (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1534                 (match_operand:SI 2 "register_operand" "r")))]
1535   ""
1536   "andn %2,%1,%0")
1537
1538 (define_expand "iordi3"
1539   [(set (match_operand:DI 0 "register_operand" "")
1540         (ior:DI (match_operand:DI 1 "arith_double_operand" "")
1541                 (match_operand:DI 2 "arith_double_operand" "")))]
1542   ""
1543   "")
1544
1545 (define_insn ""
1546   [(set (match_operand:DI 0 "register_operand" "=r")
1547         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
1548                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1549   ""
1550   "*
1551 {
1552   rtx op2 = operands[2];
1553
1554   /* If constant is postive, upper bits zeroed, otherwise unchanged
1555    * give the assembler a chance to pick the move instruction. */
1556   if (GET_CODE (op2) == CONST_INT)
1557     {
1558       int sign = INTVAL (op2);
1559       if (sign < 0)
1560         return \"mov -1,%0\;or %R1,%2,%R0\";
1561       return \"mov %1,%0\;or %R1,%2,%R0\";
1562     }
1563   else if (GET_CODE (op2) == CONST_DOUBLE)
1564     {
1565       int sign = CONST_DOUBLE_HIGH (op2);
1566       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1567                              CONST_DOUBLE_LOW (operands[1]));
1568       if (sign < 0)
1569         return \"mov -1,%0\;or %R1,%2,%R0\";
1570       return \"mov %1,%0\;or %R1,%2,%R0\";
1571     }
1572   return \"or %1,%2,%0\;or %R1,%R2,%R0\";
1573 }"
1574   [(set_attr "length" "2")])
1575
1576 (define_insn "iorsi3"
1577   [(set (match_operand:SI 0 "register_operand" "=r")
1578         (ior:SI (match_operand:SI 1 "arith_operand" "%r")
1579                 (match_operand:SI 2 "arith_operand" "rI")))]
1580   ""
1581   "or %1,%2,%0")
1582
1583 (define_insn ""
1584   [(set (match_operand:DI 0 "register_operand" "=r")
1585         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1586                 (match_operand:DI 2 "register_operand" "r")))]
1587   ""
1588   "orn %2,%1,%0\;orn %R2,%R1,%R0"
1589   [(set_attr "length" "2")])
1590
1591 (define_insn ""
1592   [(set (match_operand:SI 0 "register_operand" "=r")
1593         (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1594                 (match_operand:SI 2 "register_operand" "r")))]
1595   ""
1596   "orn %2,%1,%0")
1597
1598 (define_expand "xordi3"
1599   [(set (match_operand:DI 0 "register_operand" "")
1600         (xor:DI (match_operand:DI 1 "arith_double_operand" "")
1601                 (match_operand:DI 2 "arith_double_operand" "")))]
1602   ""
1603   "")
1604
1605 (define_insn ""
1606   [(set (match_operand:DI 0 "register_operand" "=r")
1607         (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
1608                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1609   ""
1610   "*
1611 {
1612   rtx op2 = operands[2];
1613
1614   /* If constant is postive, upper bits zeroed, otherwise unchanged
1615    * give the assembler a chance to pick the move instruction. */
1616   if (GET_CODE (op2) == CONST_INT)
1617     {
1618       int sign = INTVAL (op2);
1619       if (sign < 0)
1620         return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
1621       return \"mov %1,%0\;xor %R1,%2,%R0\";
1622     }
1623   else if (GET_CODE (op2) == CONST_DOUBLE)
1624     {
1625       int sign = CONST_DOUBLE_HIGH (op2);
1626       operands[2] = gen_rtx (CONST_INT, VOIDmode,
1627                              CONST_DOUBLE_LOW (operands[1]));
1628       if (sign < 0)
1629         return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
1630       return \"mov %1,%0\;xor %R1,%2,%R0\";
1631     }
1632   return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
1633 }"
1634   [(set_attr "length" "2")])
1635
1636 (define_insn "xorsi3"
1637   [(set (match_operand:SI 0 "register_operand" "=r")
1638         (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
1639                 (match_operand:SI 2 "arith_operand" "rI")))]
1640   ""
1641   "xor %r1,%2,%0")
1642
1643 ;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
1644 ;; Combine now canonicalizes to the rightmost expression.
1645 (define_insn ""
1646   [(set (match_operand:DI 0 "register_operand" "=r")
1647         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
1648                         (match_operand:DI 2 "register_operand" "r"))))]
1649   ""
1650   "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
1651   [(set_attr "length" "2")])
1652
1653 (define_insn ""
1654   [(set (match_operand:SI 0 "register_operand" "=r")
1655         (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1656                         (match_operand:SI 2 "arith_operand" "rI"))))]
1657   ""
1658   "xnor %r1,%2,%0")
1659
1660 ;; These correspond to the above in the case where we also (or only)
1661 ;; want to set the condition code.  
1662
1663 (define_insn ""
1664   [(set (reg:CC 0)
1665         (compare:CC
1666          (match_operator:SI 2 "cc_arithop"
1667                             [(match_operand:SI 0 "arith_operand" "%r")
1668                              (match_operand:SI 1 "arith_operand" "rI")])
1669          (const_int 0)))]
1670   ""
1671   "%A2cc %0,%1,%%g0"
1672   [(set_attr "type" "compare")])
1673
1674 (define_insn ""
1675   [(set (reg:CC 0)
1676         (compare:CC
1677          (match_operator:SI 3 "cc_arithop"
1678                             [(match_operand:SI 1 "arith_operand" "%r")
1679                              (match_operand:SI 2 "arith_operand" "rI")])
1680          (const_int 0)))
1681    (set (match_operand:SI 0 "register_operand" "=r")
1682         (match_dup 3))]
1683   ""
1684   "%A3cc %1,%2,%0")
1685
1686 (define_insn ""
1687   [(set (reg:CC 0)
1688         (compare:CC
1689          (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
1690                          (match_operand:SI 1 "arith_operand" "rI")))
1691          (const_int 0)))]
1692   ""
1693   "xnorcc %r0,%1,%%g0"
1694   [(set_attr "type" "compare")])
1695
1696 (define_insn ""
1697   [(set (reg:CC 0)
1698         (compare:CC
1699          (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
1700                          (match_operand:SI 2 "arith_operand" "rI")))
1701          (const_int 0)))
1702    (set (match_operand:SI 0 "register_operand" "=r")
1703         (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
1704   ""
1705   "xnorcc %r1,%2,%0")
1706
1707 (define_insn ""
1708   [(set (reg:CC 0)
1709         (compare:CC
1710          (match_operator:SI 2 "cc_arithopn"
1711                             [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
1712                              (match_operand:SI 1 "reg_or_0_operand" "rJ")])
1713          (const_int 0)))]
1714   ""
1715   "%B2cc %r1,%0,%%g0"
1716   [(set_attr "type" "compare")])
1717
1718 (define_insn ""
1719   [(set (reg:CC 0)
1720         (compare:CC
1721          (match_operator:SI 3 "cc_arithopn"
1722                             [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
1723                              (match_operand:SI 2 "reg_or_0_operand" "rJ")])
1724          (const_int 0)))
1725    (set (match_operand:SI 0 "register_operand" "=r")
1726         (match_dup 3))]
1727   ""
1728   "%B3cc %r2,%1,%0")
1729
1730 ;; We cannot use the "neg" pseudo insn because the Sun assembler
1731 ;; does not know how to make it work for constants.
1732
1733 (define_insn "negdi2"
1734   [(set (match_operand:DI 0 "register_operand" "=r")
1735         (neg:DI (match_operand:DI 1 "register_operand" "r")))
1736    (clobber (reg:SI 0))]
1737   ""
1738   "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
1739   [(set_attr "type" "unary")
1740    (set_attr "length" "2")])
1741
1742 (define_insn "negsi2"
1743   [(set (match_operand:SI 0 "general_operand" "=r")
1744         (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
1745   ""
1746   "sub %%g0,%1,%0"
1747   [(set_attr "type" "unary")])
1748
1749 (define_insn ""
1750   [(set (reg:CC_NOOV 0)
1751         (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
1752                          (const_int 0)))]
1753   ""
1754   "subcc %%g0,%0,%%g0"
1755   [(set_attr "type" "compare")])
1756
1757 (define_insn ""
1758   [(set (reg:CC_NOOV 0)
1759         (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
1760                          (const_int 0)))
1761    (set (match_operand:SI 0 "register_operand" "=r")
1762         (neg:SI (match_dup 1)))]
1763   ""
1764   "subcc %%g0,%1,%0"
1765   [(set_attr "type" "unary")])
1766
1767 ;; We cannot use the "not" pseudo insn because the Sun assembler
1768 ;; does not know how to make it work for constants.
1769 (define_expand "one_cmpldi2"
1770   [(set (match_operand:DI 0 "register_operand" "=r")
1771         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
1772   ""
1773   "")
1774
1775 (define_insn ""
1776   [(set (match_operand:DI 0 "register_operand" "=r")
1777         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
1778   ""
1779   "*
1780 {
1781   rtx op1 = operands[1];
1782
1783   if (GET_CODE (op1) == CONST_INT)
1784     {
1785       int sign = INTVAL (op1);
1786       if (sign < 0)
1787         return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
1788       return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
1789     }
1790   else if (GET_CODE (op1) == CONST_DOUBLE)
1791     {
1792       int sign = CONST_DOUBLE_HIGH (op1);
1793       operands[1] = gen_rtx (CONST_INT, VOIDmode,
1794                              CONST_DOUBLE_LOW (operands[1]));
1795       if (sign < 0)
1796         return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
1797       return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
1798     }
1799   return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\";
1800 }"
1801   [(set_attr "type" "unary")
1802    (set_attr "length" "2")])
1803
1804 (define_insn "one_cmplsi2"
1805   [(set (match_operand:SI 0 "register_operand" "=r")
1806         (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
1807   ""
1808   "xnor %%g0,%1,%0"
1809   [(set_attr "type" "unary")])
1810
1811 (define_insn ""
1812   [(set (reg:CC 0)
1813         (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
1814                     (const_int 0)))]
1815   ""
1816   "xnorcc %%g0,%0,%%g0"
1817   [(set_attr "type" "compare")])
1818
1819 (define_insn ""
1820   [(set (reg:CC 0)
1821         (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
1822                     (const_int 0)))
1823    (set (match_operand:SI 0 "register_operand" "=r")
1824         (not:SI (match_dup 1)))]
1825   ""
1826   "xnorcc %%g0,%1,%0"
1827   [(set_attr "type" "unary")])
1828 \f
1829 ;; Floating point arithmetic instructions.
1830
1831 (define_insn "adddf3"
1832   [(set (match_operand:DF 0 "register_operand" "=f")
1833         (plus:DF (match_operand:DF 1 "register_operand" "f")
1834                  (match_operand:DF 2 "register_operand" "f")))]
1835   ""
1836   "faddd %1,%2,%0"
1837   [(set_attr "type" "fp")])
1838
1839 (define_insn "addsf3"
1840   [(set (match_operand:SF 0 "register_operand" "=f")
1841         (plus:SF (match_operand:SF 1 "register_operand" "f")
1842                  (match_operand:SF 2 "register_operand" "f")))]
1843   ""
1844   "fadds %1,%2,%0"
1845   [(set_attr "type" "fp")])
1846
1847 (define_insn "subdf3"
1848   [(set (match_operand:DF 0 "register_operand" "=f")
1849         (minus:DF (match_operand:DF 1 "register_operand" "f")
1850                   (match_operand:DF 2 "register_operand" "f")))]
1851   ""
1852   "fsubd %1,%2,%0"
1853   [(set_attr "type" "fp")])
1854
1855 (define_insn "subsf3"
1856   [(set (match_operand:SF 0 "register_operand" "=f")
1857         (minus:SF (match_operand:SF 1 "register_operand" "f")
1858                   (match_operand:SF 2 "register_operand" "f")))]
1859   ""
1860   "fsubs %1,%2,%0"
1861   [(set_attr "type" "fp")])
1862
1863 (define_insn "muldf3"
1864   [(set (match_operand:DF 0 "register_operand" "=f")
1865         (mult:DF (match_operand:DF 1 "register_operand" "f")
1866                  (match_operand:DF 2 "register_operand" "f")))]
1867   ""
1868   "fmuld %1,%2,%0"
1869   [(set_attr "type" "fpmul")])
1870
1871 (define_insn "mulsf3"
1872   [(set (match_operand:SF 0 "register_operand" "=f")
1873         (mult:SF (match_operand:SF 1 "register_operand" "f")
1874                  (match_operand:SF 2 "register_operand" "f")))]
1875   ""
1876   "fmuls %1,%2,%0"
1877   [(set_attr "type" "fpmul")])
1878
1879 (define_insn "divdf3"
1880   [(set (match_operand:DF 0 "register_operand" "=f")
1881         (div:DF (match_operand:DF 1 "register_operand" "f")
1882                 (match_operand:DF 2 "register_operand" "f")))]
1883   ""
1884   "fdivd %1,%2,%0"
1885   [(set_attr "type" "fpdiv")])
1886
1887 (define_insn "divsf3"
1888   [(set (match_operand:SF 0 "register_operand" "=f")
1889         (div:SF (match_operand:SF 1 "register_operand" "f")
1890                 (match_operand:SF 2 "register_operand" "f")))]
1891   ""
1892   "fdivs %1,%2,%0"
1893   [(set_attr "type" "fpdiv")])
1894
1895 (define_insn "negdf2"
1896   [(set (match_operand:DF 0 "register_operand" "=f,f")
1897         (neg:DF (match_operand:DF 1 "register_operand" "0,f")))]
1898   ""
1899   "@
1900    fnegs %0,%0
1901    fnegs %1,%0\;fmovs %R1,%R0"
1902   [(set_attr "type" "fp")
1903    (set_attr "length" "1,2")])
1904
1905
1906 (define_insn "negsf2"
1907   [(set (match_operand:SF 0 "register_operand" "=f")
1908         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
1909   ""
1910   "fnegs %1,%0"
1911   [(set_attr "type" "fp")])
1912
1913 (define_insn "absdf2"
1914   [(set (match_operand:DF 0 "register_operand" "=f,f")
1915         (abs:DF (match_operand:DF 1 "register_operand" "0,f")))]
1916   ""
1917   "@
1918    fabss %0,%0
1919    fabss %1,%0\;fmovs %R1,%R0"
1920   [(set_attr "type" "fp")
1921    (set_attr "length" "1,2")])
1922
1923 (define_insn "abssf2"
1924   [(set (match_operand:SF 0 "register_operand" "=f")
1925         (abs:SF (match_operand:SF 1 "register_operand" "f")))]
1926   ""
1927   "fabss %1,%0"
1928   [(set_attr "type" "fp")])
1929
1930 (define_insn "sqrtdf2"
1931   [(set (match_operand:DF 0 "register_operand" "=f")
1932         (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
1933   ""
1934   "fsqrtd %1,%0"
1935   [(set_attr "type" "fpsqrt")])
1936
1937 (define_insn "sqrtsf2"
1938   [(set (match_operand:SF 0 "register_operand" "=f")
1939         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
1940   ""
1941   "fsqrts %1,%0"
1942   [(set_attr "type" "fpsqrt")])
1943 \f
1944 ;;- arithmetic shift instructions
1945
1946 ;; We can trivially handle shifting the constant 1 by 64 bits.
1947 ;; For other shifts we use the library routine.
1948 ;; ??? Questionable, we can do better than this can't we?
1949 (define_expand "ashldi3"
1950   [(parallel [(set (match_operand:DI 0 "register_operand" "")
1951                    (ashift:DI (match_operand:DI 1 "const_double_operand" "")
1952                               (match_operand:SI 2 "register_operand" "")))
1953               (clobber (reg:SI 0))])]
1954   ""
1955   "
1956 {
1957   if (GET_CODE (operands[1]) == CONST_DOUBLE
1958       && CONST_DOUBLE_HIGH (operands[1]) == 0
1959       && CONST_DOUBLE_LOW (operands[1]) == 1)
1960     operands[1] = const1_rtx;
1961   else if (operands[1] != const1_rtx)
1962     FAIL;
1963 }")
1964
1965 ;; ??? Questionable, we can do better than this can't we?
1966 (define_insn ""
1967   [(set (match_operand:DI 0 "register_operand" "=&r")
1968         (ashift:DI (const_int 1)
1969                    (match_operand:SI 2 "register_operand" "r")))
1970    (clobber (reg:SI 0))]
1971   ""
1972   "subcc %2,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%2,%R0\;sll %0,%2,%0"
1973   [(set_attr "type" "multi")
1974    (set_attr "length" "5")])
1975
1976 (define_insn "ashlsi3"
1977   [(set (match_operand:SI 0 "register_operand" "=r")
1978         (ashift:SI (match_operand:SI 1 "register_operand" "r")
1979                    (match_operand:SI 2 "arith_operand" "rI")))]
1980   ""
1981   "sll %1,%2,%0")
1982
1983 (define_insn "ashrsi3"
1984   [(set (match_operand:SI 0 "register_operand" "=r")
1985         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
1986                      (match_operand:SI 2 "arith_operand" "rI")))]
1987   ""
1988   "sra %1,%2,%0")
1989
1990 (define_insn "lshrsi3"
1991   [(set (match_operand:SI 0 "register_operand" "=r")
1992         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1993                      (match_operand:SI 2 "arith_operand" "rI")))]
1994   ""
1995   "srl %1,%2,%0")
1996 \f
1997 ;; Unconditional and other jump instructions
1998 ;; Note that for the Sparc, by setting the annul bit on an unconditional
1999 ;; branch, the following insn is never executed.  This saves us a nop,
2000 ;; but requires a debugger which can handle annuled branches.
2001 (define_insn "jump"
2002   [(set (pc) (label_ref (match_operand 0 "" "")))]
2003   ""
2004   "b%* %l0"
2005   [(set_attr "type" "branch")])
2006
2007 (define_expand "tablejump"
2008   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2009               (use (label_ref (match_operand 1 "" "")))])]
2010   ""
2011   "
2012 {
2013   /* We need to use the PC value in %o7 that was set up when the address
2014      of the label was loaded into a register, so we need different RTL.  */
2015   if (flag_pic)
2016     {
2017       emit_insn (gen_pic_tablejump (operands[0], operands[1]));
2018       DONE;
2019     }
2020 }")
2021
2022 (define_insn "pic_tablejump"
2023   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2024    (use (label_ref (match_operand 1 "" "")))
2025    (use (reg:SI 15))]
2026   ""
2027   "jmp %%o7+%0%#"
2028   [(set_attr "type" "branch")])
2029
2030 (define_insn ""
2031   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2032    (use (label_ref (match_operand 1 "" "")))]
2033   ""
2034   "jmp %a0%#"
2035   [(set_attr "type" "branch")])
2036
2037 (define_insn ""
2038   [(set (pc) (label_ref (match_operand 0 "" "")))
2039    (set (reg:SI 15) (label_ref (match_dup 0)))]
2040   ""
2041   "call %l0%#"
2042   [(set_attr "type" "branch")])
2043
2044 ;; This pattern recognizes the "instruction" that appears in 
2045 ;; a function call that wants a structure value, 
2046 ;; to inform the called function if compiled with Sun CC.
2047 ;(define_insn ""
2048 ;  [(match_operand:SI 0 "immediate_operand" "")]
2049 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
2050 ;  "unimp %0"
2051 ;  [(set_attr "type" "marker")])
2052
2053 ;;- jump to subroutine
2054 (define_expand "call"
2055   ;; Note that this expression is not used for generating RTL.
2056   ;; All the RTL is generated explicitly below.
2057   [(call (match_operand:SI 0 "call_operand" "")
2058          (match_operand 3 "" "i"))]
2059   ;; operands[2] is next_arg_register
2060   ;; operands[3] is struct_value_size_rtx.
2061   ""
2062   "
2063 {
2064   rtx fn_rtx, nregs_rtx;
2065
2066   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
2067     {
2068       /* This is really a PIC sequence.  We want to represent
2069          it as a funny jump so it's delay slots can be filled. 
2070
2071          ??? But if this really *is* a CALL, will not it clobber the
2072          call-clobbered registers?  We lose this if it is a JUMP_INSN.
2073          Why cannot we have delay slots filled if it were a CALL?  */
2074
2075       if (INTVAL (operands[3]) > 0)
2076         emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2077                                  gen_rtx (SET, VOIDmode, pc_rtx,
2078                                           XEXP (operands[0], 0)),
2079                                  operands[3],
2080                                  gen_rtx (CLOBBER, VOIDmode,
2081                                           gen_rtx (REG, SImode, 15)))));
2082       else
2083         emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2084                                  gen_rtx (SET, VOIDmode, pc_rtx,
2085                                           XEXP (operands[0], 0)),
2086                                  gen_rtx (CLOBBER, VOIDmode,
2087                                           gen_rtx (REG, SImode, 15)))));
2088       goto finish_call;
2089     }
2090
2091   fn_rtx = operands[0];
2092
2093   /* Count the number of parameter registers being used by this call.
2094      if that argument is NULL, it means we are using them all, which
2095      means 6 on the sparc.  */
2096 #if 0
2097   if (operands[2])
2098     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
2099   else
2100     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2101 #else
2102   nregs_rtx = const0_rtx;
2103 #endif
2104
2105   if (INTVAL (operands[3]) > 0)
2106     emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2107                              gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2108                              operands[3],
2109                              gen_rtx (CLOBBER, VOIDmode,
2110                                                gen_rtx (REG, SImode, 15)))));
2111   else
2112     emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2113                              gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2114                              gen_rtx (CLOBBER, VOIDmode,
2115                                                gen_rtx (REG, SImode, 15)))));
2116
2117  finish_call:
2118 #if 0
2119   /* If this call wants a structure value,
2120      emit an unimp insn to let the called function know about this.  */
2121   if (INTVAL (operands[3]) > 0)
2122     {
2123       rtx insn = emit_insn (operands[3]);
2124       SCHED_GROUP_P (insn) = 1;
2125     }
2126 #endif
2127
2128   DONE;
2129 }")
2130
2131 (define_insn ""
2132   [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2133          (match_operand 1 "" ""))
2134    (clobber (reg:SI 15))]
2135   ;;- Do not use operand 1 for most machines.
2136   ""
2137   "*
2138 {
2139   return \"call %a0,%1%#\";
2140 }"
2141   [(set_attr "type" "call")])
2142
2143 ;; This is a call that wants a structure value.
2144 (define_insn ""
2145   [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2146          (match_operand 1 "" ""))
2147    (match_operand 2 "immediate_operand" "")
2148    (clobber (reg:SI 15))]
2149   ;;- Do not use operand 1 for most machines.
2150   "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
2151   "*
2152 {
2153   return \"call %a0,%1\;nop\;unimp %2\";
2154 }"
2155   [(set_attr "type" "call_no_delay_slot")])
2156
2157 (define_expand "call_value"
2158   [(set (match_operand 0 "register_operand" "=rf")
2159         (call (match_operand:SI 1 "" "")
2160               (match_operand 4 "" "")))]
2161   ;; operand 3 is next_arg_register
2162   ""
2163   "
2164 {
2165   rtx fn_rtx, nregs_rtx;
2166   rtvec vec;
2167
2168   fn_rtx = operands[1];
2169
2170 #if 0
2171   if (operands[3])
2172     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
2173   else
2174     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2175 #else
2176   nregs_rtx = const0_rtx;
2177 #endif
2178
2179   vec = gen_rtvec (2,
2180                    gen_rtx (SET, VOIDmode, operands[0],
2181                             gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2182                    gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15)));
2183
2184   emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2185
2186   DONE;
2187 }")
2188
2189 (define_insn ""
2190   [(set (match_operand 0 "" "=rf")
2191         (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS"))
2192               (match_operand 2 "" "")))
2193    (clobber (reg:SI 15))]
2194   ;;- Do not use operand 2 for most machines.
2195   ""
2196   "*
2197 {
2198   return \"call %a1,%2%#\";
2199 }"
2200   [(set_attr "type" "call")])
2201 \f
2202 (define_insn "return"
2203   [(return)]
2204   "! TARGET_EPILOGUE"
2205   "* return output_return (operands);"
2206   [(set_attr "type" "multi")])
2207
2208 (define_insn "nop"
2209   [(const_int 0)]
2210   ""
2211   "nop")
2212
2213 (define_insn "indirect_jump"
2214   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2215   ""
2216  "jmp %a0%#"
2217  [(set_attr "type" "branch")])
2218  
2219 (define_expand "nonlocal_goto"
2220   [(match_operand:SI 0 "general_operand" "")
2221    (match_operand:SI 1 "general_operand" "")
2222    (match_operand:SI 2 "general_operand" "")
2223    (match_operand:SI 3 "" "")]
2224   ""
2225   "
2226 {
2227   rtx temp;
2228   /* Trap instruction to flush all the registers window.  */
2229   emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2230                       gen_rtvec (1, const0_rtx), 0));
2231   /* Load the fp value for the containing fn into %fp.
2232      This is needed because operands[2] refers to %fp.  */
2233   emit_move_insn (virtual_stack_vars_rtx, operands[0]);
2234   /* Find the containing function's current nonlocal goto handler,
2235      which will do any cleanups and then jump to the label.  */
2236   emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]);
2237   /* Restore %fp from stack pointer value for containing function.
2238      The restore insn that follows will move this to %sp,
2239      and reload the appropriate value into %fp.  */
2240   emit_move_insn (frame_pointer_rtx, operands[2]);
2241   /* Put in the static chain register the nonlocal label address.  */
2242   emit_move_insn (static_chain_rtx, operands[3]);
2243   /* USE of frame_pointer_rtx added for consistency; not clear if
2244      really needed.  */
2245   emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
2246   emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
2247   emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
2248   emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8)));
2249   /* Return, restoring reg window and jumping to goto handler.  */
2250   emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2251                       gen_rtvec (1, const0_rtx), 1));
2252   DONE;
2253 }")
2254
2255 ;; Special trap insn to flush register windows.
2256 (define_insn ""
2257   [(unspec_volatile [(const_int 0)] 0)]
2258   ""
2259   "ta 3")
2260
2261 (define_insn ""
2262   [(unspec_volatile [(const_int 0)] 1)]
2263   ""
2264   "jmp %%o0+0\;restore")
2265
2266 ;(define_insn "tail_call" ;; tail call
2267 ;  [(set (pc) (match_operand 0 "memory_operand" "m"))]
2268 ;  "tail_call_valid_p ()"
2269 ;  "* return output_tail_call (operands, insn);"
2270 ;  [(set_attr "type" "branch")])
2271 \f
2272 ;; Split up troublesome insns for better scheduling.  */
2273
2274 ;; The following patterns are straightforward.  They can be applied
2275 ;; either before or after register allocation.
2276
2277 (define_split
2278   [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")])
2279         (match_operand 2 "reg_or_0_operand" ""))
2280    (clobber (match_operand:SI 3 "register_operand" ""))]
2281   "! flag_pic"
2282   [(set (match_dup 3) (high:SI (match_dup 1)))
2283    (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))])
2284         (match_dup 2))]
2285   "")
2286
2287 (define_split
2288   [(set (match_operator 0 "memop"
2289                         [(match_operand:SI 1 "immediate_operand" "")])
2290         (match_operand 2 "general_operand" ""))
2291    (clobber (match_operand:SI 3 "register_operand" ""))]
2292   "flag_pic"
2293   [(set (match_op_dup 0 [(match_dup 1)])
2294         (match_dup 2))]
2295   "
2296 {
2297   operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]),
2298                                         operands[3], 0);
2299 }")
2300
2301 (define_split
2302   [(set (match_operand 0 "register_operand" "")
2303         (match_operator 1 "memop"
2304                         [(match_operand:SI 2 "immediate_operand" "")]))]
2305   "flag_pic"
2306   [(set (match_dup 0)
2307         (match_op_dup 1 [(match_dup 2)]))]
2308   "
2309 {
2310   operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]),
2311                                         operands[0], 0);
2312 }")
2313
2314 ;; Sign- and Zero-extend operations can have symbolic memory operands.
2315
2316 (define_split
2317   [(set (match_operand 0 "register_operand" "")
2318         (match_operator 1 "extend_op"
2319                         [(match_operator 2 "memop"
2320                                          [(match_operand:SI 3 "immediate_operand" "")])]))]
2321   "flag_pic"
2322   [(set (match_dup 0)
2323         (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))]
2324   "
2325 {
2326   operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]),
2327                                         operands[0], 0);
2328 }")
2329
2330 (define_split
2331   [(set (match_operand:SI 0 "register_operand" "")
2332         (match_operand:SI 1 "immediate_operand" ""))]
2333   "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2334                   || GET_CODE (operands[1]) == CONST
2335                   || GET_CODE (operands[1]) == LABEL_REF)"
2336   [(set (match_dup 0) (high:SI (match_dup 1)))
2337    (set (match_dup 0)
2338         (lo_sum:SI (match_dup 0) (match_dup 1)))]
2339   "")
2340
2341 ;; LABEL_REFs are not modified by `legitimize_pic_address`
2342 ;; so do not recurse infinitely in the PIC case.
2343 (define_split
2344   [(set (match_operand:SI 0 "register_operand" "")
2345         (match_operand:SI 1 "immediate_operand" ""))]
2346   "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2347                 || GET_CODE (operands[1]) == CONST)"
2348   [(set (match_dup 0) (match_dup 1))]
2349   "
2350 {
2351   operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0);
2352 }")
2353 \f
2354 ;; These split sne/seq insns.  The forms of the resulting insns are 
2355 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
2356 ;; Nothing will look at these in detail after splitting has occurred.
2357
2358 (define_split
2359   [(set (match_operand:SI 0 "register_operand" "")
2360         (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2361    (clobber (reg:CC 0))]
2362   ""
2363   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2364                                          (const_int 0)))
2365    (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
2366   "")
2367
2368 (define_split
2369   [(set (match_operand:SI 0 "register_operand" "")
2370         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2371                        (const_int 0))))
2372    (clobber (reg:CC 0))]
2373   ""
2374   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2375                                          (const_int 0)))
2376    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
2377   "")
2378
2379 (define_split
2380   [(set (match_operand:SI 0 "register_operand" "")
2381         (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2382    (clobber (reg:CC 0))]
2383   ""
2384   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2385                                          (const_int 0)))
2386    (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
2387   "")
2388
2389 (define_split
2390   [(set (match_operand:SI 0 "register_operand" "")
2391         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2392                        (const_int 0))))
2393    (clobber (reg:CC 0))]
2394   ""
2395   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2396                                          (const_int 0)))
2397    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
2398   "")
2399
2400 (define_split
2401   [(set (match_operand:SI 0 "register_operand" "")
2402         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2403                         (const_int 0))
2404                  (match_operand:SI 2 "register_operand" "")))
2405    (clobber (reg:CC 0))]
2406   ""
2407   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2408                                          (const_int 0)))
2409    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
2410                                (match_dup 2)))]
2411   "")
2412
2413 (define_split
2414   [(set (match_operand:SI 0 "register_operand" "")
2415         (minus:SI (match_operand:SI 2 "register_operand" "")
2416                   (ne:SI (match_operand:SI 1 "register_operand" "")
2417                          (const_int 0))))
2418    (clobber (reg:CC 0))]
2419   ""
2420   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2421                                          (const_int 0)))
2422    (set (match_dup 0) (minus:SI (match_dup 2)
2423                                 (ltu:SI (reg:CC 0) (const_int 0))))]
2424   "")
2425
2426 (define_split
2427   [(set (match_operand:SI 0 "register_operand" "")
2428         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2429                         (const_int 0))
2430                  (match_operand:SI 2 "register_operand" "")))
2431    (clobber (reg:CC 0))]
2432   ""
2433   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2434                                          (const_int 0)))
2435    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
2436                                (match_dup 2)))]
2437   "")
2438
2439 (define_split
2440   [(set (match_operand:SI 0 "register_operand" "")
2441         (minus:SI (match_operand:SI 2 "register_operand" "")
2442                   (eq:SI (match_operand:SI 1 "register_operand" "")
2443                          (const_int 0))))
2444    (clobber (reg:CC 0))]
2445   ""
2446   [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2447                                          (const_int 0)))
2448    (set (match_dup 0) (minus:SI (match_dup 2)
2449                                 (geu:SI (reg:CC 0) (const_int 0))))]
2450   "")
2451 \f
2452 ;; Peepholes go at the end.
2453
2454 ;; Optimize the case of following a reg-reg move with a test
2455 ;; of reg just moved.
2456
2457 (define_peephole
2458   [(set (match_operand:SI 0 "register_operand" "=r")
2459         (match_operand:SI 1 "register_operand" "r"))
2460    (set (reg:CC 0)
2461         (compare:CC (match_operand:SI 2 "register_operand" "r")
2462                     (const_int 0)))]
2463   "rtx_equal_p (operands[2], operands[0])
2464    || rtx_equal_p (operands[2], operands[1])"
2465   "orcc %1,%%g0,%0"
2466   [(set_attr "type" "move")])
2467
2468 ;; Do {sign,zero}-extended compares somewhat more efficiently.
2469 ;; ??? Is this now the Right Way to do this?  Or will SCRATCH
2470 ;;     eventually have some impact here?
2471
2472 (define_peephole
2473   [(set (match_operand:HI 0 "register_operand" "")
2474         (match_operand:HI 1 "memory_operand" ""))
2475    (set (match_operand:SI 2 "register_operand" "")
2476         (sign_extend:SI (match_dup 0)))
2477    (set (reg:CC 0)
2478         (compare:CC (match_dup 2)
2479                     (const_int 0)))]
2480   ""
2481   "ldsh %1,%0\;orcc %0,%%g0,%2")
2482
2483 (define_peephole
2484   [(set (match_operand:QI 0 "register_operand" "")
2485         (match_operand:QI 1 "memory_operand" ""))
2486    (set (match_operand:SI 2 "register_operand" "")
2487         (sign_extend:SI (match_dup 0)))
2488    (set (reg:CC 0)
2489         (compare:CC (match_dup 2)
2490                     (const_int 0)))]
2491   ""
2492   "ldsb %1,%0\;orcc %0,%%g0,%2")
2493
2494 (define_peephole
2495   [(set (match_operand:HI 0 "register_operand" "")
2496         (match_operand:HI 1 "memory_operand" ""))
2497    (set (match_operand:SI 2 "register_operand" "")
2498         (sign_extend:SI (match_dup 0)))]
2499   "dead_or_set_p (insn, operands[0])"
2500   "*
2501 {
2502   warning (\"bad peephole\");
2503   if (! MEM_VOLATILE_P (operands[1]))
2504     abort ();
2505   return \"ldsh %1,%2\";
2506 }")
2507
2508 (define_peephole
2509   [(set (match_operand:QI 0 "register_operand" "")
2510         (match_operand:QI 1 "memory_operand" ""))
2511    (set (match_operand:SI 2 "register_operand" "")
2512         (sign_extend:SI (match_dup 0)))]
2513   "dead_or_set_p (insn, operands[0])"
2514   "*
2515 {
2516   warning (\"bad peephole\");
2517   if (! MEM_VOLATILE_P (operands[1]))
2518     abort ();
2519   return \"ldsb %1,%2\";
2520 }")
2521
2522 ;; Floating-point move peepholes
2523
2524 (define_peephole
2525   [(set (match_operand:SI 0 "register_operand" "=r")
2526         (lo_sum:SI (match_dup 0)
2527                    (match_operand:SI 1 "immediate_operand" "i")))
2528    (set (match_operand:DF 2 "register_operand" "=fr")
2529         (mem:DF (match_dup 0)))]
2530   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
2531   "*
2532 {
2533   /* Go by way of output_move_double in case the register in operand 2
2534      is not properly aligned for ldd.  */
2535   operands[1] = gen_rtx (MEM, DFmode,
2536                          gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
2537   operands[0] = operands[2];
2538   return output_move_double (operands);
2539 }")
2540
2541 (define_peephole
2542   [(set (match_operand:SI 0 "register_operand" "=r")
2543         (lo_sum:SI (match_dup 0)
2544                    (match_operand:SI 1 "immediate_operand" "i")))
2545    (set (match_operand:SF 2 "register_operand" "=fr")
2546         (mem:SF (match_dup 0)))]
2547   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
2548   "ld [%0+%%lo(%a1)],%2")
2549
2550 ;; Return peepholes.  First the "normal" ones
2551
2552 (define_insn ""
2553   [(set (match_operand:SI 0 "restore_operand" "")
2554         (match_operand:SI 1 "arith_operand" "rI"))
2555    (return)]
2556   "! TARGET_EPILOGUE"
2557   "*
2558 {
2559   if (current_function_returns_struct)
2560     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
2561   else
2562     return \"ret\;restore %%g0,%1,%Y0\";
2563 }"
2564   [(set_attr "type" "multi")])
2565
2566 (define_insn ""
2567   [(set (match_operand:SI 0 "restore_operand" "")
2568         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
2569                  (match_operand:SI 2 "arith_operand" "rI")))
2570    (return)]
2571   "! TARGET_EPILOGUE"
2572   "*
2573 {
2574   if (current_function_returns_struct)
2575     return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
2576   else
2577     return \"ret\;restore %r1,%2,%Y0\";
2578 }"
2579   [(set_attr "type" "multi")])
2580
2581 ;; Turned off because it should never match (subtracting a constant
2582 ;; is turned into addition) and because it would do the wrong thing
2583 ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
2584 ;;(define_insn ""
2585 ;;  [(set (match_operand:SI 0 "restore_operand" "")
2586 ;;      (minus:SI (match_operand:SI 1 "register_operand" "r")
2587 ;;                (match_operand:SI 2 "small_int" "I")))
2588 ;;   (return)]
2589 ;;  "! TARGET_EPILOGUE"
2590 ;;  "ret\;restore %1,-(%2),%Y0"
2591 ;;  [(set_attr "type" "multi")])
2592
2593 ;; The following pattern is only generated by delayed-branch scheduling,
2594 ;; when the insn winds up in the epilogue.
2595 (define_insn ""
2596   [(set (reg:SF 32)
2597         (match_operand:SF 0 "register_operand" "f"))
2598    (return)]
2599   "! TARGET_EPILOGUE"
2600   "ret\;fmovs %0,%%f0")
2601
2602 ;; Now peepholes to go a call followed by a jump.
2603
2604 (define_peephole
2605   [(parallel [(set (match_operand 0 "" "")
2606                    (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r"))
2607                          (match_operand 2 "" "")))
2608               (clobber (reg:SI 15))])
2609    (set (pc) (label_ref (match_operand 3 "" "")))]
2610   "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
2611   "*
2612 {
2613   return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
2614 }")
2615
2616 (define_peephole
2617   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2618                     (match_operand 1 "" ""))
2619               (clobber (reg:SI 15))])
2620    (set (pc) (label_ref (match_operand 2 "" "")))]
2621   "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
2622   "*
2623 {
2624   return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
2625 }")
2626
2627 (define_peephole
2628   [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
2629                    (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
2630                              (reg:SI 0)))
2631               (clobber (reg:CC 0))])
2632    (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]
2633   ""
2634   "subxcc %r1,0,%0"
2635   [(set_attr "type" "compare")])
2636
2637 ;;- Local variables:
2638 ;;- mode:emacs-lisp
2639 ;;- comment-start: ";;- "
2640 ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
2641 ;;- eval: (modify-syntax-entry ?[ "(]")
2642 ;;- eval: (modify-syntax-entry ?] ")[")
2643 ;;- eval: (modify-syntax-entry ?{ "(}")
2644 ;;- eval: (modify-syntax-entry ?} "){")
2645 ;;- End: