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