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)
5 ;; This file is part of GNU CC.
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)
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.
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.
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24 ;; Insn type. Used to default other attribute values.
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.
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"))
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" ""))
40 (const_string "false")))
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))
48 (eq_attr "type" "store,fpstore")
49 (if_then_else (match_operand
0 "symbolic_memory_operand" "")
50 (const_int
2) (const_int
1))
52 (eq_attr "type" "address") (const_int
2)
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))
59 (eq_attr "type" "multi") (const_int
2)
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))]
68 (define_asm_attributes
69 [(set_attr "length" "
1")
70 (set_attr "type" "multi")])
72 ;; Attributes for instruction and branch scheduling
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")
80 (const_string "false"))
81 (eq_attr "type" "address")
82 (if_then_else (eq_attr "use_clobbered" "false")
84 (const_string "false"))]
85 (if_then_else (eq_attr "length" "
1")
87 (const_string "false"))))
89 (define_delay (eq_attr "type" "call")
90 [(eq_attr "in_call_delay" "true") (nil) (nil)])
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.
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")))
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")))
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")))
115 (define_delay (eq_attr "type" "branch")
116 [(eq_attr "in_branch_delay" "true")
117 (nil) (eq_attr "in_annul_branch_delay" "true")])
119 (define_delay (eq_attr "type" "uncond_branch")
120 [(eq_attr "in_uncond_branch_delay" "true")
123 ;; Function units of the SPARC
125 ;; (define_function_unit {name} {num-units} {n-users} {test}
126 ;; {ready-delay} {busy-delay} [{conflict-list}])
129 ;; (Noted only for documentation; units that take one cycle do not need to
132 ;; (define_function_unit "alu"
1 0
133 ;; (eq_attr "type" "unary,binary,move,address")
1 0)
135 ;; Memory with load-delay of
1 (i.e.,
2 cycle load).
136 (define_function_unit "memory"
1 0 (eq_attr "type" "load,fpload")
2 0)
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
154 ;; The CY7C602 can only support
2 fp isnsn simultaneously.
155 ;; More insns cause the chip to stall.
157 (define_function_unit "fp_alu"
1 2 (eq_attr "type" "fp")
5 0)
158 (define_function_unit "fp_mul"
1 2 (eq_attr "type" "fpmul")
7 0)
159 (define_function_unit "fp_div"
1 2 (eq_attr "type" "fpdiv")
37 0)
160 (define_function_unit "fp_sqrt"
1 2 (eq_attr "type" "fpsqrt")
63 0)
162 ;; Compare instructions.
163 ;; This controls RTL generation and register allocation.
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.
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
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.
178 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
180 (define_expand "cmpsi"
182 (compare:CC (match_operand:SI
0 "register_operand" "")
183 (match_operand:SI
1 "arith_operand" "")))]
187 sparc_compare_op0 = operands[
0];
188 sparc_compare_op1 = operands[
1];
192 (define_expand "cmpsf"
194 (compare:CCFP (match_operand:SF
0 "register_operand" "")
195 (match_operand:SF
1 "register_operand" "")))]
199 sparc_compare_op0 = operands[
0];
200 sparc_compare_op1 = operands[
1];
204 (define_expand "cmpdf"
206 (compare:CCFP (match_operand:DF
0 "register_operand" "")
207 (match_operand:DF
1 "register_operand" "")))]
211 sparc_compare_op0 = operands[
0];
212 sparc_compare_op1 = operands[
1];
216 (define_expand "cmptf"
218 (compare:CCFP (match_operand:TF
0 "register_operand" "")
219 (match_operand:TF
1 "register_operand" "")))]
223 sparc_compare_op0 = operands[
0];
224 sparc_compare_op1 = operands[
1];
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.
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))])]
241 "{ operands[
3] = gen_reg_rtx (SImode); }")
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))])]
250 "{ operands[
3] = gen_reg_rtx (SImode); }")
253 [(set (match_operand:SI
0 "register_operand" "")
254 (eq:SI (match_dup
1) (const_int
0)))]
257 { if (GET_MODE (sparc_compare_op0) == SImode)
259 emit_insn (gen_seq_special (operands[
0], sparc_compare_op0,
264 operands[
1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
268 [(set (match_operand:SI
0 "register_operand" "")
269 (ne:SI (match_dup
1) (const_int
0)))]
272 { if (GET_MODE (sparc_compare_op0) == SImode)
274 emit_insn (gen_sne_special (operands[
0], sparc_compare_op0,
279 operands[
1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
283 [(set (match_operand:SI
0 "register_operand" "")
284 (gt:SI (match_dup
1) (const_int
0)))]
287 { operands[
1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
290 [(set (match_operand:SI
0 "register_operand" "")
291 (lt:SI (match_dup
1) (const_int
0)))]
294 { operands[
1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
297 [(set (match_operand:SI
0 "register_operand" "")
298 (ge:SI (match_dup
1) (const_int
0)))]
301 { operands[
1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
304 [(set (match_operand:SI
0 "register_operand" "")
305 (le:SI (match_dup
1) (const_int
0)))]
308 { operands[
1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
310 (define_expand "sgtu"
311 [(set (match_operand:SI
0 "register_operand" "")
312 (gtu:SI (match_dup
1) (const_int
0)))]
318 /* We can do ltu easily, so if both operands are registers, swap them and
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))
325 tem = sparc_compare_op0;
326 sparc_compare_op0 = sparc_compare_op1;
327 sparc_compare_op1 = tem;
328 emit_insn (gen_sltu (operands[
0]));
332 operands[
1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
335 (define_expand "sltu"
336 [(set (match_operand:SI
0 "register_operand" "")
337 (ltu:SI (match_dup
1) (const_int
0)))]
340 { operands[
1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
343 (define_expand "sgeu"
344 [(set (match_operand:SI
0 "register_operand" "")
345 (geu:SI (match_dup
1) (const_int
0)))]
348 { operands[
1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
351 (define_expand "sleu"
352 [(set (match_operand:SI
0 "register_operand" "")
353 (leu:SI (match_dup
1) (const_int
0)))]
359 /* We can do geu easily, so if both operands are registers, swap them and
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))
366 tem = sparc_compare_op0;
367 sparc_compare_op0 = sparc_compare_op1;
368 sparc_compare_op1 = tem;
369 emit_insn (gen_sgeu (operands[
0]));
373 operands[
1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
376 ;; Now the DEFINE_INSNs for the compare and scc cases. First the compares.
380 (compare:CC (match_operand:SI
0 "register_operand" "r")
381 (match_operand:SI
1 "arith_operand" "rI")))]
384 [(set_attr "type" "compare")])
388 (compare:CCFPE (match_operand:DF
0 "register_operand" "f")
389 (match_operand:DF
1 "register_operand" "f")))]
392 [(set_attr "type" "fpcmp")])
396 (compare:CCFPE (match_operand:SF
0 "register_operand" "f")
397 (match_operand:SF
1 "register_operand" "f")))]
400 [(set_attr "type" "fpcmp")])
404 (compare:CCFPE (match_operand:TF
0 "register_operand" "f")
405 (match_operand:TF
1 "register_operand" "f")))]
408 [(set_attr "type" "fpcmp")])
412 (compare:CCFP (match_operand:DF
0 "register_operand" "f")
413 (match_operand:DF
1 "register_operand" "f")))]
416 [(set_attr "type" "fpcmp")])
420 (compare:CCFP (match_operand:SF
0 "register_operand" "f")
421 (match_operand:SF
1 "register_operand" "f")))]
424 [(set_attr "type" "fpcmp")])
428 (compare:CCFP (match_operand:TF
0 "register_operand" "f")
429 (match_operand:TF
1 "register_operand" "f")))]
432 [(set_attr "type" "fpcmp")])
434 ;; The SEQ and SNE patterns are special because they can be done
435 ;; without any branching and do not involve a COMPARE.
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))]
442 "subcc %%g0,%
1,%%g0\;addx %%g0,
0,%
0"
443 [(set_attr "type" "unary")
444 (set_attr "length" "
2")])
447 [(set (match_operand:SI
0 "register_operand" "=r")
448 (neg:SI (ne:SI (match_operand:SI
1 "register_operand" "r")
450 (clobber (reg:CC
0))]
452 "subcc %%g0,%
1,%%g0\;subx %%g0,
0,%
0"
453 [(set_attr "type" "unary")
454 (set_attr "length" "
2")])
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))]
461 "subcc %%g0,%
1,%%g0\;subx %%g0,-
1,%
0"
462 [(set_attr "type" "unary")
463 (set_attr "length" "
2")])
466 [(set (match_operand:SI
0 "register_operand" "=r")
467 (neg:SI (eq:SI (match_operand:SI
1 "register_operand" "r")
469 (clobber (reg:CC
0))]
471 "subcc %%g0,%
1,%%g0\;addx %%g0,-
1,%
0"
472 [(set_attr "type" "unary")
473 (set_attr "length" "
2")])
475 ;; We can also do (x + (i ==
0)) and related, so put them in.
478 [(set (match_operand:SI
0 "register_operand" "=r")
479 (plus:SI (ne:SI (match_operand:SI
1 "register_operand" "r")
481 (match_operand:SI
2 "register_operand" "r")))
482 (clobber (reg:CC
0))]
484 "subcc %%g0,%
1,%%g0\;addx %
2,
0,%
0"
485 [(set_attr "length" "
2")])
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")
492 (clobber (reg:CC
0))]
494 "subcc %%g0,%
1,%%g0\;subx %
2,
0,%
0"
495 [(set_attr "length" "
2")])
498 [(set (match_operand:SI
0 "register_operand" "=r")
499 (plus:SI (eq:SI (match_operand:SI
1 "register_operand" "r")
501 (match_operand:SI
2 "register_operand" "r")))
502 (clobber (reg:CC
0))]
504 "subcc %%g0,%
1,%%g0\;subx %
2,-
1,%
0"
505 [(set_attr "length" "
2")])
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")
512 (clobber (reg:CC
0))]
514 "subcc %%g0,%
1,%%g0\;addx %
2,-
1,%
0"
515 [(set_attr "length" "
2")])
517 ;; We can also do GEU and LTU directly, but these operate after a
521 [(set (match_operand:SI
0 "register_operand" "=r")
522 (ltu:SI (reg:CC
0) (const_int
0)))]
525 [(set_attr "type" "misc")])
528 [(set (match_operand:SI
0 "register_operand" "=r")
529 (neg:SI (ltu:SI (reg:CC
0) (const_int
0))))]
532 [(set_attr "type" "misc")])
534 ;; ??? Combine should canonicalize these next two to the same pattern.
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")))]
541 [(set_attr "type" "unary")])
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"))))]
549 [(set_attr "type" "unary")])
552 [(set (match_operand:SI
0 "register_operand" "=r")
553 (geu:SI (reg:CC
0) (const_int
0)))]
556 [(set_attr "type" "misc")])
559 [(set (match_operand:SI
0 "register_operand" "=r")
560 (neg:SI (geu:SI (reg:CC
0) (const_int
0))))]
563 [(set_attr "type" "misc")])
565 ;; We can also do (x + ((unsigned) i >=
0)) and related, so put them in.
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")))]
573 [(set_attr "type" "unary")])
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"))))]
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))))]
589 [(set_attr "type" "unary")])
591 ;; ??? Combine should canonicalize these next two to the same pattern.
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))))]
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"))))]
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")))]
614 [(set_attr "type" "unary")])
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))))]
622 [(set_attr "type" "unary")])
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.
628 [(set (match_operand:SI
0 "register_operand" "=r")
629 (match_operator:SI
1 "noov_compare_op" [(reg
0) (const_int
0)]))]
631 "* return output_scc_insn (operands, insn); "
632 [(set_attr "type" "multi")
633 (set_attr "length" "
3")])
635 ;; These control RTL generation for conditional jump insns
639 (if_then_else (eq (match_dup
1) (const_int
0))
640 (label_ref (match_operand
0 "" ""))
644 { operands[
1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); }")
648 (if_then_else (ne (match_dup
1) (const_int
0))
649 (label_ref (match_operand
0 "" ""))
653 { operands[
1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); }")
657 (if_then_else (gt (match_dup
1) (const_int
0))
658 (label_ref (match_operand
0 "" ""))
662 { operands[
1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
664 (define_expand "bgtu"
666 (if_then_else (gtu (match_dup
1) (const_int
0))
667 (label_ref (match_operand
0 "" ""))
671 { operands[
1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
676 (if_then_else (lt (match_dup
1) (const_int
0))
677 (label_ref (match_operand
0 "" ""))
681 { operands[
1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
683 (define_expand "bltu"
685 (if_then_else (ltu (match_dup
1) (const_int
0))
686 (label_ref (match_operand
0 "" ""))
690 { operands[
1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
695 (if_then_else (ge (match_dup
1) (const_int
0))
696 (label_ref (match_operand
0 "" ""))
700 { operands[
1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
702 (define_expand "bgeu"
704 (if_then_else (geu (match_dup
1) (const_int
0))
705 (label_ref (match_operand
0 "" ""))
709 { operands[
1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
714 (if_then_else (le (match_dup
1) (const_int
0))
715 (label_ref (match_operand
0 "" ""))
719 { operands[
1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
721 (define_expand "bleu"
723 (if_then_else (leu (match_dup
1) (const_int
0))
724 (label_ref (match_operand
0 "" ""))
728 { operands[
1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
731 ;; Now match both normal and inverted jump.
735 (if_then_else (match_operator
0 "noov_compare_op"
736 [(reg
0) (const_int
0)])
737 (label_ref (match_operand
1 "" ""))
742 return output_cbranch (operands[
0],
1,
0,
743 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
746 [(set_attr "type" "branch")])
750 (if_then_else (match_operator
0 "noov_compare_op"
751 [(reg
0) (const_int
0)])
753 (label_ref (match_operand
1 "" ""))))]
757 return output_cbranch (operands[
0],
1,
1,
758 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
761 [(set_attr "type" "branch")])
765 (define_expand "movsi"
766 [(set (match_operand:SI
0 "general_operand" "")
767 (match_operand:SI
1 "general_operand" ""))]
771 if (emit_move_sequence (operands, SImode,
0))
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"))]
782 if (emit_move_sequence (operands, SImode, operands[
2]))
785 /* We don't want the clobber emitted, so handle this ourselves. */
786 emit_insn (gen_rtx (SET, VOIDmode, operands[
0], operands[
1]));
790 ;; We must support both 'r' and 'f' registers here, because combine may
791 ;; convert SFmode hard registers to SImode hard registers when simplifying
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.
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"
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,*,*,*,*,*")])
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)
820 [(set (match_operand:SI
0 "register_operand" "=r")
821 (match_operand:SI
1 "move_pic_label" "i"))
822 (set (reg:SI
15) (pc))]
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")])
829 [(set (match_operand:DI
0 "register_operand" "=r")
830 (high:DI (match_operand
1 "" "")))]
834 rtx op0 = operands[
0];
835 rtx op1 = operands[
1];
837 if (GET_CODE (op1) == CONST_INT)
839 operands[
0] = operand_subword (op0,
1,
0, DImode);
840 output_asm_insn (
\"sethi %%hi(%a1),%
0\", operands);
842 operands[
0] = operand_subword (op0,
0,
0, DImode);
843 if (INTVAL (op1) <
0)
844 output_asm_insn (
\"mov -
1,%
0\", operands);
846 output_asm_insn (
\"mov
0,%
0\", operands);
848 else if (GET_CODE (op1) == CONST_DOUBLE)
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);
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);
861 [(set_attr "type" "move")
862 (set_attr "length" "
2")])
864 ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
865 ;; confuse them with real addresses.
867 [(set (match_operand:SI
0 "register_operand" "=r")
868 (high:SI (unspec:SI [(match_operand
1 "" "")]
0)))]
871 [(set_attr "type" "move")
872 (set_attr "length" "
1")])
875 [(set (match_operand:SI
0 "register_operand" "=r")
876 (high:SI (match_operand
1 "" "")))]
879 [(set_attr "type" "move")
880 (set_attr "length" "
1")])
883 [(set (match_operand:HI
0 "register_operand" "=r")
884 (high:HI (match_operand
1 "" "")))]
887 [(set_attr "type" "move")
888 (set_attr "length" "
1")])
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")))]
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
\";
903 ;; Need to set length for this arith insn because operand2
904 ;; is not an "arith_operand".
905 [(set_attr "length" "
1")])
907 ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
908 ;; confuse them with real addresses.
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)))]
915 ;; Need to set length for this arith insn because operand2
916 ;; is not an "arith_operand".
917 [(set_attr "length" "
1")])
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")))]
925 ;; Need to set length for this arith insn because operand2
926 ;; is not an "arith_operand".
927 [(set_attr "length" "
1")])
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"))]
934 "sethi %%hi(%a0),%
2\;st %r1,[%
2+%%lo(%a0)]"
935 [(set_attr "type" "store")
936 (set_attr "length" "
2")])
938 (define_expand "movhi"
939 [(set (match_operand:HI
0 "general_operand" "")
940 (match_operand:HI
1 "general_operand" ""))]
944 if (emit_move_sequence (operands, HImode,
0))
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"
959 [(set_attr "type" "move,move,load,store")
960 (set_attr "length" "*,
1,*,
1")])
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")))]
968 [(set_attr "length" "
1")])
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"))]
975 "sethi %%hi(%a0),%
2\;sth %r1,[%
2+%%lo(%a0)]"
976 [(set_attr "type" "store")
977 (set_attr "length" "
2")])
979 (define_expand "movqi"
980 [(set (match_operand:QI
0 "general_operand" "")
981 (match_operand:QI
1 "general_operand" ""))]
985 if (emit_move_sequence (operands, QImode,
0))
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"
1000 [(set_attr "type" "move,move,load,store")
1001 (set_attr "length" "*,
1,*,
1")])
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))]
1008 "or %
1,%%lo(%a2),%
0"
1009 [(set_attr "length" "
1")])
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"))]
1016 "sethi %%hi(%a0),%
2\;stb %r1,[%
2+%%lo(%a0)]"
1017 [(set_attr "type" "store")
1018 (set_attr "length" "
2")])
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))])]
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)
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]);
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))]
1061 "* return output_block_move (operands);"
1062 [(set_attr "type" "multi")
1063 (set_attr "length" "
6")])
1065 ;; Floating point move insns
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.
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"
1076 switch (which_alternative)
1079 return output_move_quad (operands);
1081 return output_fp_move_quad (operands);
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\";
1089 [(set_attr "type" "load,fpload,store")
1090 (set_attr "length" "
5,
5,
5")])
1092 (define_expand "movtf"
1093 [(set (match_operand:TF
0 "general_operand" "")
1094 (match_operand:TF
1 "general_operand" ""))]
1098 if (emit_move_sequence (operands, TFmode,
0))
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)"
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);
1113 [(set_attr "type" "fp,move,fpstore,store,fpload,load,multi,multi")
1114 (set_attr "length" "
4,
4,
5,
5,
5,
5,
5,
5")])
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"))]
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)]
\";
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)]
\";
1129 [(set_attr "type" "store")
1130 (set_attr "length" "
5")])
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.
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"
1141 switch (which_alternative)
1144 return output_move_double (operands);
1146 return output_fp_move_double (operands);
1148 operands[
1] = adj_offsettable_operand (operands[
0],
4);
1149 return
\"st %%g0,%
0\;st %%g0,%
1\";
1152 [(set_attr "type" "load,fpload,store")
1153 (set_attr "length" "
3,
3,
3")])
1155 (define_expand "movdf"
1156 [(set (match_operand:DF
0 "general_operand" "")
1157 (match_operand:DF
1 "general_operand" ""))]
1161 if (emit_move_sequence (operands, DFmode,
0))
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)"
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);
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")])
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"))]
1186 output_asm_insn (
\"sethi %%hi(%a0),%
2\", operands);
1187 if (which_alternative ==
0)
1188 return
\"std %
1,[%
2+%%lo(%a0)]
\";
1190 return
\"st %%g0,[%
2+%%lo(%a0)]\;st %%g0,[%
2+%%lo(%a0+
4)]
\";
1192 [(set_attr "type" "store")
1193 (set_attr "length" "
3")])
1195 ;; Double-word move insns.
1197 (define_expand "movdi"
1198 [(set (match_operand:DI
0 "reg_or_nonsymb_mem_operand" "")
1199 (match_operand:DI
1 "general_operand" ""))]
1203 if (emit_move_sequence (operands, DImode,
0))
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"
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);
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")])
1222 ;; Floating-point move insns.
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.
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"
1233 switch (which_alternative)
1236 return singlemove_string (operands);
1238 return
\"ld %
1,%
0\";
1240 return
\"st %%g0,%
0\";
1243 [(set_attr "type" "load,fpload,store")
1244 (set_attr "length" "
2,
1,
1")])
1246 (define_expand "movsf"
1247 [(set (match_operand:SF
0 "general_operand" "")
1248 (match_operand:SF
1 "general_operand" ""))]
1252 if (emit_move_sequence (operands, SFmode,
0))
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)"
1264 st %r1,[%%fp-
4]\;ld [%%fp-
4],%
0
1269 [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store")])
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"))]
1276 "sethi %%hi(%a0),%
2\;st %r1,[%
2+%%lo(%a0)]"
1277 [(set_attr "type" "store")
1278 (set_attr "length" "
2")])
1280 ;;- zero extension instructions
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.
1286 (define_expand "zero_extendhisi2"
1287 [(set (match_operand:SI
0 "register_operand" "")
1288 (zero_extend:SI (match_operand:HI
1 "register_operand" "")))]
1292 rtx temp = gen_reg_rtx (SImode);
1293 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode,
16);
1295 if (GET_CODE (operand1) == SUBREG)
1296 operand1 = XEXP (operand1,
0);
1298 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
0),
1300 emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
1305 [(set (match_operand:SI
0 "register_operand" "=r")
1306 (zero_extend:SI (match_operand:HI
1 "memory_operand" "m")))]
1309 [(set_attr "type" "load")])
1311 (define_expand "zero_extendqihi2"
1312 [(set (match_operand:HI
0 "register_operand" "")
1313 (zero_extend:HI (match_operand:QI
1 "register_operand" "")))]
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"
1325 [(set_attr "type" "unary,move,load")
1326 (set_attr "length" "
1")])
1328 (define_expand "zero_extendqisi2"
1329 [(set (match_operand:SI
0 "register_operand" "")
1330 (zero_extend:SI (match_operand:QI
1 "register_operand" "")))]
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"
1342 [(set_attr "type" "unary,move,load")
1343 (set_attr "length" "
1")])
1347 (compare:CC (zero_extend:SI (match_operand:QI
0 "register_operand" "r"))
1350 "andcc %
0,
0xff,%%g0"
1351 [(set_attr "type" "compare")])
1355 (compare:CC (zero_extend:SI (match_operand:QI
1 "register_operand" "r"))
1357 (set (match_operand:SI
0 "register_operand" "=r")
1358 (zero_extend:SI (match_dup
1)))]
1361 [(set_attr "type" "unary")])
1363 ;;- sign extension instructions
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.
1369 (define_expand "extendhisi2"
1370 [(set (match_operand:SI
0 "register_operand" "")
1371 (sign_extend:SI (match_operand:HI
1 "register_operand" "")))]
1375 rtx temp = gen_reg_rtx (SImode);
1376 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode,
16);
1378 if (GET_CODE (operand1) == SUBREG)
1379 operand1 = XEXP (operand1,
0);
1381 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
0),
1383 emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
1388 [(set (match_operand:SI
0 "register_operand" "=r")
1389 (sign_extend:SI (match_operand:HI
1 "memory_operand" "m")))]
1392 [(set_attr "type" "load")])
1394 (define_expand "extendqihi2"
1395 [(set (match_operand:HI
0 "register_operand" "")
1396 (sign_extend:HI (match_operand:QI
1 "register_operand" "")))]
1400 rtx temp = gen_reg_rtx (SImode);
1401 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode,
24);
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),
1409 if (GET_MODE (operand0) != SImode)
1410 operand0 = gen_rtx (SUBREG, SImode, operand0,
0);
1411 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1416 [(set (match_operand:HI
0 "register_operand" "=r")
1417 (sign_extend:HI (match_operand:QI
1 "memory_operand" "m")))]
1420 [(set_attr "type" "load")])
1422 (define_expand "extendqisi2"
1423 [(set (match_operand:SI
0 "register_operand" "")
1424 (sign_extend:SI (match_operand:QI
1 "register_operand" "")))]
1428 rtx temp = gen_reg_rtx (SImode);
1429 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode,
24);
1431 if (GET_CODE (operand1) == SUBREG)
1432 operand1 = XEXP (operand1,
0);
1433 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
0),
1435 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1440 [(set (match_operand:SI
0 "register_operand" "=r")
1441 (sign_extend:SI (match_operand:QI
1 "memory_operand" "m")))]
1444 [(set_attr "type" "load")])
1446 ;; Special pattern for optimizing bit-field compares. This is needed
1447 ;; because combine uses this as a canonical form.
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"))
1456 "INTVAL (operands[
2]) >
19"
1459 int len = INTVAL (operands[
1]);
1460 int pos =
32 - INTVAL (operands[
2]) - len;
1461 unsigned mask = ((
1 << len) -
1) << pos;
1463 operands[
1] = gen_rtx (CONST_INT, VOIDmode, mask);
1464 return
\"andcc %
0,%
1,%%g0
\";
1467 ;; Conversions between float, double and long double.
1469 (define_insn "extendsfdf2"
1470 [(set (match_operand:DF
0 "register_operand" "=f")
1472 (match_operand:SF
1 "register_operand" "f")))]
1475 [(set_attr "type" "fp")])
1477 (define_insn "extendsftf2"
1478 [(set (match_operand:TF
0 "register_operand" "=f")
1480 (match_operand:SF
1 "register_operand" "f")))]
1483 [(set_attr "type" "fp")])
1485 (define_insn "extenddftf2"
1486 [(set (match_operand:TF
0 "register_operand" "=f")
1488 (match_operand:DF
1 "register_operand" "f")))]
1491 [(set_attr "type" "fp")])
1493 (define_insn "truncdfsf2"
1494 [(set (match_operand:SF
0 "register_operand" "=f")
1496 (match_operand:DF
1 "register_operand" "f")))]
1499 [(set_attr "type" "fp")])
1501 (define_insn "trunctfsf2"
1502 [(set (match_operand:SF
0 "register_operand" "=f")
1504 (match_operand:TF
1 "register_operand" "f")))]
1507 [(set_attr "type" "fp")])
1509 (define_insn "trunctfdf2"
1510 [(set (match_operand:DF
0 "register_operand" "=f")
1512 (match_operand:TF
1 "register_operand" "f")))]
1515 [(set_attr "type" "fp")])
1517 ;; Conversion between fixed point and floating point.
1519 (define_insn "floatsisf2"
1520 [(set (match_operand:SF
0 "general_operand" "=f")
1521 (float:SF (match_operand:SI
1 "nonimmediate_operand" "rfm")))]
1523 "* return output_floatsisf2 (operands);"
1524 [(set_attr "type" "fp")
1525 (set_attr "length" "
3")])
1527 (define_insn "floatsidf2"
1528 [(set (match_operand:DF
0 "general_operand" "=f")
1529 (float:DF (match_operand:SI
1 "nonimmediate_operand" "rfm")))]
1531 "* return output_floatsidf2 (operands);"
1532 [(set_attr "type" "fp")
1533 (set_attr "length" "
3")])
1535 (define_insn "floatsitf2"
1536 [(set (match_operand:TF
0 "general_operand" "=f")
1537 (float:TF (match_operand:SI
1 "nonimmediate_operand" "rfm")))]
1539 "* return output_floatsitf2 (operands);"
1540 [(set_attr "type" "fp")
1541 (set_attr "length" "
3")])
1543 ;; Convert a float to an actual integer.
1544 ;; Truncation is performed as part of the conversion.
1546 (define_insn "fix_truncsfsi2"
1547 [(set (match_operand:SI
0 "general_operand" "=rm")
1548 (fix:SI (fix:SF (match_operand:SF
1 "general_operand" "fm"))))
1549 (clobber (match_scratch:SF
2 "=&f"))]
1553 if (FP_REG_P (operands[
1]))
1554 output_asm_insn (
\"fstoi %
1,%
2\", operands);
1556 output_asm_insn (
\"ld %
1,%
2\;fstoi %
2,%
2\", operands);
1557 if (GET_CODE (operands[
0]) == MEM)
1558 return
\"st %
2,%
0\";
1560 return
\"st %
2,[%%fp-
4]\;ld [%%fp-
4],%
0\";
1562 [(set_attr "type" "fp")
1563 (set_attr "length" "
3")])
1565 (define_insn "fix_truncdfsi2"
1566 [(set (match_operand:SI
0 "general_operand" "=rm")
1567 (fix:SI (fix:DF (match_operand:DF
1 "general_operand" "fm"))))
1568 (clobber (match_scratch:DF
2 "=&f"))]
1572 if (FP_REG_P (operands[
1]))
1573 output_asm_insn (
\"fdtoi %
1,%
2\", operands);
1577 xoperands[
0] = operands[
2];
1578 xoperands[
1] = operands[
1];
1579 output_asm_insn (output_fp_move_double (xoperands), xoperands);
1580 output_asm_insn (
\"fdtoi %
2,%
2\", operands);
1582 if (GET_CODE (operands[
0]) == MEM)
1583 return
\"st %
2,%
0\";
1585 return
\"st %
2,[%%fp-
4]\;ld [%%fp-
4],%
0\";
1587 [(set_attr "type" "fp")
1588 (set_attr "length" "
3")])
1590 (define_insn "fix_trunctfsi2"
1591 [(set (match_operand:SI
0 "general_operand" "=rm")
1592 (fix:SI (fix:TF (match_operand:TF
1 "general_operand" "fm"))))
1593 (clobber (match_scratch:DF
2 "=&f"))]
1597 if (FP_REG_P (operands[
1]))
1598 output_asm_insn (
\"fqtoi %
1,%
2\", operands);
1602 xoperands[
0] = operands[
2];
1603 xoperands[
1] = operands[
1];
1604 output_asm_insn (output_fp_move_quad (xoperands), xoperands);
1605 output_asm_insn (
\"fqtoi %
2,%
2\", operands);
1607 if (GET_CODE (operands[
0]) == MEM)
1608 return
\"st %
2,%
0\";
1610 return
\"st %
2,[%%fp-
4]\;ld [%%fp-
4],%
0\";
1612 [(set_attr "type" "fp")
1613 (set_attr "length" "
3")])
1615 ;; Allow combiner to combine a fix_trunctfsi2 with a floatsitf2
1616 ;; This eliminates
2 useless instructions.
1617 ;; The first one matches if the fixed result is needed. The second one
1618 ;; matches if the fixed result is not needed.
1621 [(set (match_operand:TF
0 "general_operand" "=f")
1622 (float:TF (fix:SI (fix:TF (match_operand:TF
1 "general_operand" "fm")))))
1623 (set (match_operand:SI
2 "general_operand" "=rm")
1624 (fix:SI (fix:TF (match_dup
1))))]
1628 if (FP_REG_P (operands[
1]))
1629 output_asm_insn (
\"fqtoi %
1,%
0\", operands);
1632 output_asm_insn (output_fp_move_quad (operands), operands);
1633 output_asm_insn (
\"fqtoi %
0,%
0\", operands);
1635 if (GET_CODE (operands[
2]) == MEM)
1636 return
\"st %
0,%
2\;fitoq %
0,%
0\";
1638 return
\"st %
0,[%%fp-
4]\;fitoq %
0,%
0\;ld [%%fp-
4],%
2\";
1640 [(set_attr "type" "fp")
1641 (set_attr "length" "
5")])
1644 [(set (match_operand:TF
0 "general_operand" "=f")
1645 (float:TF (fix:SI (fix:TF (match_operand:TF
1 "general_operand" "fm")))))]
1649 if (FP_REG_P (operands[
1]))
1650 output_asm_insn (
\"fqtoi %
1,%
0\", operands);
1653 output_asm_insn (output_fp_move_quad (operands), operands);
1654 output_asm_insn (
\"fqtoi %
0,%
0\", operands);
1656 return
\"fitoq %
0,%
0\";
1658 [(set_attr "type" "fp")
1659 (set_attr "length" "
3")])
1661 ;; Allow combiner to combine a fix_truncdfsi2 with a floatsidf2
1662 ;; This eliminates
2 useless instructions.
1663 ;; The first one matches if the fixed result is needed. The second one
1664 ;; matches if the fixed result is not needed.
1667 [(set (match_operand:DF
0 "general_operand" "=f")
1668 (float:DF (fix:SI (fix:DF (match_operand:DF
1 "general_operand" "fm")))))
1669 (set (match_operand:SI
2 "general_operand" "=rm")
1670 (fix:SI (fix:DF (match_dup
1))))]
1674 if (FP_REG_P (operands[
1]))
1675 output_asm_insn (
\"fdtoi %
1,%
0\", operands);
1678 output_asm_insn (output_fp_move_double (operands), operands);
1679 output_asm_insn (
\"fdtoi %
0,%
0\", operands);
1681 if (GET_CODE (operands[
2]) == MEM)
1682 return
\"st %
0,%
2\;fitod %
0,%
0\";
1684 return
\"st %
0,[%%fp-
4]\;fitod %
0,%
0\;ld [%%fp-
4],%
2\";
1686 [(set_attr "type" "fp")
1687 (set_attr "length" "
5")])
1690 [(set (match_operand:DF
0 "general_operand" "=f")
1691 (float:DF (fix:SI (fix:DF (match_operand:DF
1 "general_operand" "fm")))))]
1695 if (FP_REG_P (operands[
1]))
1696 output_asm_insn (
\"fdtoi %
1,%
0\", operands);
1699 output_asm_insn (output_fp_move_double (operands), operands);
1700 output_asm_insn (
\"fdtoi %
0,%
0\", operands);
1702 return
\"fitod %
0,%
0\";
1704 [(set_attr "type" "fp")
1705 (set_attr "length" "
3")])
1707 ;; Allow combiner to combine a fix_truncsfsi2 with a floatsisf2
1708 ;; This eliminates
2 useless instructions.
1709 ;; The first one matches if the fixed result is needed. The second one
1710 ;; matches if the fixed result is not needed.
1713 [(set (match_operand:SF
0 "general_operand" "=f")
1714 (float:SF (fix:SI (fix:SF (match_operand:SF
1 "general_operand" "fm")))))
1715 (set (match_operand:SI
2 "general_operand" "=rm")
1716 (fix:SI (fix:SF (match_dup
1))))]
1720 if (FP_REG_P (operands[
1]))
1721 output_asm_insn (
\"fstoi %
1,%
0\", operands);
1723 output_asm_insn (
\"ld %
1,%
0\;fstoi %
0,%
0\", operands);
1724 if (GET_CODE (operands[
2]) == MEM)
1725 return
\"st %
0,%
2\;fitos %
0,%
0\";
1727 return
\"st %
0,[%%fp-
4]\;fitos %
0,%
0\;ld [%%fp-
4],%
2\";
1729 [(set_attr "type" "fp")
1730 (set_attr "length" "
5")])
1733 [(set (match_operand:SF
0 "general_operand" "=f")
1734 (float:SF (fix:SI (fix:SF (match_operand:SF
1 "general_operand" "fm")))))]
1738 if (FP_REG_P (operands[
1]))
1739 output_asm_insn (
\"fstoi %
1,%
0\", operands);
1741 output_asm_insn (
\"ld %
1,%
0\;fstoi %
0,%
0\", operands);
1742 return
\"fitos %
0,%
0\";
1744 [(set_attr "type" "fp")
1745 (set_attr "length" "
3")])
1747 ;;- arithmetic instructions
1749 (define_insn "adddi3"
1750 [(set (match_operand:DI
0 "register_operand" "=r")
1751 (plus:DI (match_operand:DI
1 "arith_double_operand" "%r")
1752 (match_operand:DI
2 "arith_double_operand" "rHI")))
1753 (clobber (reg:SI
0))]
1757 rtx op2 = operands[
2];
1759 /* If constant is positive, upper bits zeroed, otherwise unchanged.
1760 Give the assembler a chance to pick the move instruction. */
1761 if (GET_CODE (op2) == CONST_INT)
1763 int sign = INTVAL (op2);
1765 return
\"addcc %R1,%
2,%R0\;addx %
1,-
1,%
0\";
1766 return
\"addcc %R1,%
2,%R0\;addx %
1,
0,%
0\";
1768 else if (GET_CODE (op2) == CONST_DOUBLE)
1770 int sign = CONST_DOUBLE_HIGH (op2);
1771 operands[
2] = gen_rtx (CONST_INT, VOIDmode,
1772 CONST_DOUBLE_LOW (operands[
1]));
1774 return
\"addcc %R1,%
2,%R0\;addx %
1,-
1,%
0\";
1775 return
\"addcc %R1,%
2,%R0\;addx %
1,
0,%
0\";
1777 return
\"addcc %R1,%R2,%R0\;addx %
1,%
2,%
0\";
1779 [(set_attr "length" "
2")])
1781 (define_insn "addsi3"
1782 [(set (match_operand:SI
0 "register_operand" "=r")
1783 (plus:SI (match_operand:SI
1 "arith_operand" "%r")
1784 (match_operand:SI
2 "arith_operand" "rI")))]
1789 [(set (reg:CC_NOOV
0)
1790 (compare:CC_NOOV (plus:SI (match_operand:SI
0 "arith_operand" "%r")
1791 (match_operand:SI
1 "arith_operand" "rI"))
1795 [(set_attr "type" "compare")])
1798 [(set (reg:CC_NOOV
0)
1799 (compare:CC_NOOV (plus:SI (match_operand:SI
1 "arith_operand" "%r")
1800 (match_operand:SI
2 "arith_operand" "rI"))
1802 (set (match_operand:SI
0 "register_operand" "=r")
1803 (plus:SI (match_dup
1) (match_dup
2)))]
1807 (define_insn "subdi3"
1808 [(set (match_operand:DI
0 "register_operand" "=r")
1809 (minus:DI (match_operand:DI
1 "register_operand" "r")
1810 (match_operand:DI
2 "arith_double_operand" "rHI")))
1811 (clobber (reg:SI
0))]
1815 rtx op2 = operands[
2];
1817 /* If constant is positive, upper bits zeroed, otherwise unchanged.
1818 Give the assembler a chance to pick the move instruction. */
1819 if (GET_CODE (op2) == CONST_INT)
1821 int sign = INTVAL (op2);
1823 return
\"subcc %R1,%
2,%R0\;subx %
1,-
1,%
0\";
1824 return
\"subcc %R1,%
2,%R0\;subx %
1,
0,%
0\";
1826 else if (GET_CODE (op2) == CONST_DOUBLE)
1828 int sign = CONST_DOUBLE_HIGH (op2);
1829 operands[
2] = gen_rtx (CONST_INT, VOIDmode,
1830 CONST_DOUBLE_LOW (operands[
1]));
1832 return
\"subcc %R1,%
2,%R0\;subx %
1,-
1,%
0\";
1833 return
\"subcc %R1,%
2,%R0\;subx %
1,
0,%
0\";
1835 return
\"subcc %R1,%R2,%R0\;subx %
1,%
2,%
0\";
1837 [(set_attr "length" "
2")])
1839 (define_insn "subsi3"
1840 [(set (match_operand:SI
0 "register_operand" "=r")
1841 (minus:SI (match_operand:SI
1 "register_operand" "r")
1842 (match_operand:SI
2 "arith_operand" "rI")))]
1847 [(set (reg:CC_NOOV
0)
1848 (compare:CC_NOOV (minus:SI (match_operand:SI
0 "register_operand" "r")
1849 (match_operand:SI
1 "arith_operand" "rI"))
1853 [(set_attr "type" "compare")])
1856 [(set (reg:CC_NOOV
0)
1857 (compare:CC_NOOV (minus:SI (match_operand:SI
1 "register_operand" "r")
1858 (match_operand:SI
2 "arith_operand" "rI"))
1860 (set (match_operand:SI
0 "register_operand" "=r")
1861 (minus:SI (match_dup
1) (match_dup
2)))]
1865 (define_insn "mulsi3"
1866 [(set (match_operand:SI
0 "register_operand" "=r")
1867 (mult:SI (match_operand:SI
1 "arith_operand" "%r")
1868 (match_operand:SI
2 "arith_operand" "rI")))]
1869 "TARGET_V8 || TARGET_SPARCLITE"
1872 ;; It is not known whether this will match.
1875 [(set (match_operand:SI
0 "register_operand" "=r")
1876 (mult:SI (match_operand:SI
1 "arith_operand" "%r")
1877 (match_operand:SI
2 "arith_operand" "rI")))
1878 (set (reg:CC_NOOV
0)
1879 (compare:CC_NOOV (mult:SI (match_dup
1) (match_dup
2))
1881 "TARGET_V8 || TARGET_SPARCLITE"
1884 (define_insn "mulsidi3"
1885 [(set (match_operand:DI
0 "register_operand" "=r")
1886 (mult:DI (sign_extend:DI (match_operand:SI
1 "arith_operand" "%r"))
1887 (sign_extend:DI (match_operand:SI
2 "arith_operand" "rI"))))]
1888 "TARGET_V8 || TARGET_SPARCLITE"
1889 "smul %
1,%
2,%R0\;rd %y,%
0"
1890 [(set_attr "length" "
2")])
1892 (define_insn "umulsidi3"
1893 [(set (match_operand:DI
0 "register_operand" "=r")
1894 (mult:DI (zero_extend:DI (match_operand:SI
1 "arith_operand" "%r"))
1895 (zero_extend:DI (match_operand:SI
2 "arith_operand" "rI"))))]
1896 "TARGET_V8 || TARGET_SPARCLITE"
1897 "umul %
1,%
2,%R0\;rd %y,%
0"
1898 [(set_attr "length" "
2")])
1900 ;; The architecture specifies that there must be
3 instructions between
1901 ;; a y register write and a use of it for correct results.
1903 (define_insn "divsi3"
1904 [(set (match_operand:SI
0 "register_operand" "=r")
1905 (div:SI (match_operand:SI
1 "register_operand" "r")
1906 (match_operand:SI
2 "arith_operand" "rI")))
1907 (clobber (match_scratch:SI
3 "=&r"))]
1909 "sra %
1,
31,%
3\;wr %%g0,%
3,%%y\;nop\;nop\;nop\;sdiv %
1,%
2,%
0"
1910 [(set_attr "length" "
3")])
1912 ;; It is not known whether this will match.
1915 [(set (match_operand:SI
0 "register_operand" "=r")
1916 (div:SI (match_operand:SI
1 "register_operand" "r")
1917 (match_operand:SI
2 "arith_operand" "rI")))
1919 (compare:CC (div:SI (match_dup
1) (match_dup
2))
1921 (clobber (match_scratch:SI
3 "=&r"))]
1923 "sra %
1,
31,%
3\;wr %%g0,%
3,%%y\;nop\;nop\;nop\;sdivcc %
1,%
2,%
0"
1924 [(set_attr "length" "
3")])
1926 (define_insn "udivsi3"
1927 [(set (match_operand:SI
0 "register_operand" "=r")
1928 (udiv:SI (match_operand:SI
1 "register_operand" "r")
1929 (match_operand:SI
2 "arith_operand" "rI")))]
1931 "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %
1,%
2,%
0"
1932 [(set_attr "length" "
2")])
1934 ;; It is not known whether this will match.
1937 [(set (match_operand:SI
0 "register_operand" "=r")
1938 (udiv:SI (match_operand:SI
1 "register_operand" "r")
1939 (match_operand:SI
2 "arith_operand" "rI")))
1941 (compare:CC (udiv:SI (match_dup
1) (match_dup
2))
1944 "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %
1,%
2,%
0"
1945 [(set_attr "length" "
2")])
1947 ;;- and instructions
1948 ;; We define DImode
`and` so with DImode
`not` we can get
1949 ;; DImode
`andn`. Other combinations are possible.
1951 (define_expand "anddi3"
1952 [(set (match_operand:DI
0 "register_operand" "")
1953 (and:DI (match_operand:DI
1 "arith_double_operand" "")
1954 (match_operand:DI
2 "arith_double_operand" "")))]
1959 [(set (match_operand:DI
0 "register_operand" "=r")
1960 (and:DI (match_operand:DI
1 "arith_double_operand" "%r")
1961 (match_operand:DI
2 "arith_double_operand" "rHI")))]
1965 rtx op2 = operands[
2];
1967 /* If constant is positive, upper bits zeroed, otherwise unchanged.
1968 Give the assembler a chance to pick the move instruction. */
1969 if (GET_CODE (op2) == CONST_INT)
1971 int sign = INTVAL (op2);
1973 return
\"mov %
1,%
0\;and %R1,%
2,%R0
\";
1974 return
\"mov
0,%
0\;and %R1,%
2,%R0
\";
1976 else if (GET_CODE (op2) == CONST_DOUBLE)
1978 int sign = CONST_DOUBLE_HIGH (op2);
1979 operands[
2] = gen_rtx (CONST_INT, VOIDmode,
1980 CONST_DOUBLE_LOW (operands[
1]));
1982 return
\"mov %
1,%
0\;and %R1,%
2,%R0
\";
1983 return
\"mov
0,%
0\;and %R1,%
2,%R0
\";
1985 return
\"and %
1,%
2,%
0\;and %R1,%R2,%R0
\";
1987 [(set_attr "length" "
2")])
1989 (define_insn "andsi3"
1990 [(set (match_operand:SI
0 "register_operand" "=r")
1991 (and:SI (match_operand:SI
1 "arith_operand" "%r")
1992 (match_operand:SI
2 "arith_operand" "rI")))]
1997 [(set (match_operand:SI
0 "register_operand" "")
1998 (and:SI (match_operand:SI
1 "register_operand" "")
1999 (match_operand:SI
2 "" "")))]
2000 "GET_CODE (operands[
2]) == CONST_INT
2001 && !SMALL_INT (operands[
2])
2002 && (INTVAL (operands[
2]) &
0x3ff) ==
0x3ff"
2003 [(set (match_dup
0) (match_dup
3))
2004 (set (match_dup
0) (and:SI (not:SI (match_dup
0)) (match_dup
1)))]
2007 operands[
3] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[
2]));
2011 [(set (match_operand:DI
0 "register_operand" "=r")
2012 (and:DI (not:DI (match_operand:DI
1 "register_operand" "r"))
2013 (match_operand:DI
2 "register_operand" "r")))]
2015 "andn %
2,%
1,%
0\;andn %R2,%R1,%R0"
2016 [(set_attr "length" "
2")])
2019 [(set (match_operand:SI
0 "register_operand" "=r")
2020 (and:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
2021 (match_operand:SI
2 "register_operand" "r")))]
2025 (define_expand "iordi3"
2026 [(set (match_operand:DI
0 "register_operand" "")
2027 (ior:DI (match_operand:DI
1 "arith_double_operand" "")
2028 (match_operand:DI
2 "arith_double_operand" "")))]
2033 [(set (match_operand:DI
0 "register_operand" "=r")
2034 (ior:DI (match_operand:DI
1 "arith_double_operand" "%r")
2035 (match_operand:DI
2 "arith_double_operand" "rHI")))]
2039 rtx op2 = operands[
2];
2041 /* If constant is positive, upper bits zeroed, otherwise unchanged.
2042 Give the assembler a chance to pick the move instruction. */
2043 if (GET_CODE (op2) == CONST_INT)
2045 int sign = INTVAL (op2);
2047 return
\"mov -
1,%
0\;or %R1,%
2,%R0
\";
2048 return
\"mov %
1,%
0\;or %R1,%
2,%R0
\";
2050 else if (GET_CODE (op2) == CONST_DOUBLE)
2052 int sign = CONST_DOUBLE_HIGH (op2);
2053 operands[
2] = gen_rtx (CONST_INT, VOIDmode,
2054 CONST_DOUBLE_LOW (operands[
1]));
2056 return
\"mov -
1,%
0\;or %R1,%
2,%R0
\";
2057 return
\"mov %
1,%
0\;or %R1,%
2,%R0
\";
2059 return
\"or %
1,%
2,%
0\;or %R1,%R2,%R0
\";
2061 [(set_attr "length" "
2")])
2063 (define_insn "iorsi3"
2064 [(set (match_operand:SI
0 "register_operand" "=r")
2065 (ior:SI (match_operand:SI
1 "arith_operand" "%r")
2066 (match_operand:SI
2 "arith_operand" "rI")))]
2071 [(set (match_operand:SI
0 "register_operand" "")
2072 (ior:SI (match_operand:SI
1 "register_operand" "")
2073 (match_operand:SI
2 "" "")))]
2074 "GET_CODE (operands[
2]) == CONST_INT
2075 && !SMALL_INT (operands[
2])
2076 && (INTVAL (operands[
2]) &
0x3ff) ==
0x3ff"
2077 [(set (match_dup
0) (match_dup
3))
2078 (set (match_dup
0) (ior:SI (not:SI (match_dup
0)) (match_dup
1)))]
2081 operands[
3] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[
2]));
2085 [(set (match_operand:DI
0 "register_operand" "=r")
2086 (ior:DI (not:DI (match_operand:DI
1 "register_operand" "r"))
2087 (match_operand:DI
2 "register_operand" "r")))]
2089 "orn %
2,%
1,%
0\;orn %R2,%R1,%R0"
2090 [(set_attr "length" "
2")])
2093 [(set (match_operand:SI
0 "register_operand" "=r")
2094 (ior:SI (not:SI (match_operand:SI
1 "register_operand" "r"))
2095 (match_operand:SI
2 "register_operand" "r")))]
2099 (define_expand "xordi3"
2100 [(set (match_operand:DI
0 "register_operand" "")
2101 (xor:DI (match_operand:DI
1 "arith_double_operand" "")
2102 (match_operand:DI
2 "arith_double_operand" "")))]
2107 [(set (match_operand:DI
0 "register_operand" "=r")
2108 (xor:DI (match_operand:DI
1 "arith_double_operand" "%r")
2109 (match_operand:DI
2 "arith_double_operand" "rHI")))]
2113 rtx op2 = operands[
2];
2115 /* If constant is positive, upper bits zeroed, otherwise unchanged.
2116 Give the assembler a chance to pick the move instruction. */
2117 if (GET_CODE (op2) == CONST_INT)
2119 int sign = INTVAL (op2);
2121 return
\"xor %
1,-
1,%
0\;xor %R1,%
2,%R0
\";
2122 return
\"mov %
1,%
0\;xor %R1,%
2,%R0
\";
2124 else if (GET_CODE (op2) == CONST_DOUBLE)
2126 int sign = CONST_DOUBLE_HIGH (op2);
2127 operands[
2] = gen_rtx (CONST_INT, VOIDmode,
2128 CONST_DOUBLE_LOW (operands[
1]));
2130 return
\"xor %
1,-
1,%
0\;xor %R1,%
2,%R0
\";
2131 return
\"mov %
1,%
0\;xor %R1,%
2,%R0
\";
2133 return
\"xor %
1,%
2,%
0\;xor %R1,%R2,%R0
\";
2135 [(set_attr "length" "
2")])
2137 (define_insn "xorsi3"
2138 [(set (match_operand:SI
0 "register_operand" "=r")
2139 (xor:SI (match_operand:SI
1 "arith_operand" "%rJ")
2140 (match_operand:SI
2 "arith_operand" "rI")))]
2145 [(set (match_operand:SI
0 "register_operand" "")
2146 (xor:SI (match_operand:SI
1 "register_operand" "")
2147 (match_operand:SI
2 "" "")))]
2148 "GET_CODE (operands[
2]) == CONST_INT
2149 && !SMALL_INT (operands[
2])
2150 && (INTVAL (operands[
2]) &
0x3ff) ==
0x3ff"
2151 [(set (match_dup
0) (match_dup
3))
2152 (set (match_dup
0) (not:SI (xor:SI (match_dup
0) (match_dup
1))))]
2155 operands[
3] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[
2]));
2159 [(set (match_operand:SI
0 "register_operand" "")
2160 (not:SI (xor:SI (match_operand:SI
1 "register_operand" "")
2161 (match_operand:SI
2 "" ""))))]
2162 "GET_CODE (operands[
2]) == CONST_INT
2163 && !SMALL_INT (operands[
2])
2164 && (INTVAL (operands[
2]) &
0x3ff) ==
0x3ff"
2165 [(set (match_dup
0) (match_dup
3))
2166 (set (match_dup
0) (xor:SI (match_dup
0) (match_dup
1)))]
2169 operands[
3] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[
2]));
2172 ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
2173 ;; Combine now canonicalizes to the rightmost expression.
2175 [(set (match_operand:DI
0 "register_operand" "=r")
2176 (not:DI (xor:DI (match_operand:DI
1 "register_operand" "r")
2177 (match_operand:DI
2 "register_operand" "r"))))]
2179 "xnor %
1,%
2,%
0\;xnor %R1,%R2,%R0"
2180 [(set_attr "length" "
2")])
2183 [(set (match_operand:SI
0 "register_operand" "=r")
2184 (not:SI (xor:SI (match_operand:SI
1 "reg_or_0_operand" "rJ")
2185 (match_operand:SI
2 "arith_operand" "rI"))))]
2189 ;; These correspond to the above in the case where we also (or only)
2190 ;; want to set the condition code.
2195 (match_operator:SI
2 "cc_arithop"
2196 [(match_operand:SI
0 "arith_operand" "%r")
2197 (match_operand:SI
1 "arith_operand" "rI")])
2201 [(set_attr "type" "compare")])
2206 (match_operator:SI
3 "cc_arithop"
2207 [(match_operand:SI
1 "arith_operand" "%r")
2208 (match_operand:SI
2 "arith_operand" "rI")])
2210 (set (match_operand:SI
0 "register_operand" "=r")
2218 (not:SI (xor:SI (match_operand:SI
0 "reg_or_0_operand" "%rJ")
2219 (match_operand:SI
1 "arith_operand" "rI")))
2222 "xnorcc %r0,%
1,%%g0"
2223 [(set_attr "type" "compare")])
2228 (not:SI (xor:SI (match_operand:SI
1 "reg_or_0_operand" "%rJ")
2229 (match_operand:SI
2 "arith_operand" "rI")))
2231 (set (match_operand:SI
0 "register_operand" "=r")
2232 (not:SI (xor:SI (match_dup
1) (match_dup
2))))]
2239 (match_operator:SI
2 "cc_arithopn"
2240 [(not:SI (match_operand:SI
0 "arith_operand" "rI"))
2241 (match_operand:SI
1 "reg_or_0_operand" "rJ")])
2245 [(set_attr "type" "compare")])
2250 (match_operator:SI
3 "cc_arithopn"
2251 [(not:SI (match_operand:SI
1 "arith_operand" "rI"))
2252 (match_operand:SI
2 "reg_or_0_operand" "rJ")])
2254 (set (match_operand:SI
0 "register_operand" "=r")
2259 ;; We cannot use the "neg" pseudo insn because the Sun assembler
2260 ;; does not know how to make it work for constants.
2262 (define_insn "negdi2"
2263 [(set (match_operand:DI
0 "register_operand" "=r")
2264 (neg:DI (match_operand:DI
1 "register_operand" "r")))
2265 (clobber (reg:SI
0))]
2267 "subcc %%g0,%R1,%R0\;subx %%g0,%
1,%
0"
2268 [(set_attr "type" "unary")
2269 (set_attr "length" "
2")])
2271 (define_insn "negsi2"
2272 [(set (match_operand:SI
0 "general_operand" "=r")
2273 (neg:SI (match_operand:SI
1 "arith_operand" "rI")))]
2276 [(set_attr "type" "unary")])
2279 [(set (reg:CC_NOOV
0)
2280 (compare:CC_NOOV (neg:SI (match_operand:SI
0 "arith_operand" "rI"))
2283 "subcc %%g0,%
0,%%g0"
2284 [(set_attr "type" "compare")])
2287 [(set (reg:CC_NOOV
0)
2288 (compare:CC_NOOV (neg:SI (match_operand:SI
1 "arith_operand" "rI"))
2290 (set (match_operand:SI
0 "register_operand" "=r")
2291 (neg:SI (match_dup
1)))]
2294 [(set_attr "type" "unary")])
2296 ;; We cannot use the "not" pseudo insn because the Sun assembler
2297 ;; does not know how to make it work for constants.
2298 (define_expand "one_cmpldi2"
2299 [(set (match_operand:DI
0 "register_operand" "=r")
2300 (not:DI (match_operand:DI
1 "arith_double_operand" "rHI")))]
2305 [(set (match_operand:DI
0 "register_operand" "=r")
2306 (not:DI (match_operand:DI
1 "arith_double_operand" "rHI")))]
2310 rtx op1 = operands[
1];
2312 if (GET_CODE (op1) == CONST_INT)
2314 int sign = INTVAL (op1);
2316 return
\"xnor %%g0,%
1,%R0\;xnor %%g0,-
1,%
0\";
2317 return
\"xnor %%g0,%
1,%R0\;xnor %%g0,
0,%
0\";
2319 else if (GET_CODE (op1) == CONST_DOUBLE)
2321 int sign = CONST_DOUBLE_HIGH (op1);
2322 operands[
1] = gen_rtx (CONST_INT, VOIDmode,
2323 CONST_DOUBLE_LOW (operands[
1]));
2325 return
\"xnor %%g0,%
1,%R0\;xnor %%g0,-
1,%
0\";
2326 return
\"xnor %%g0,%
1,%R0\;xnor %%g0,
0,%
0\";
2328 return
\"xnor %%g0,%
1,%
0\;xnor %%g0,%R1,%R0
\";
2330 [(set_attr "type" "unary")
2331 (set_attr "length" "
2")])
2333 (define_insn "one_cmplsi2"
2334 [(set (match_operand:SI
0 "register_operand" "=r")
2335 (not:SI (match_operand:SI
1 "arith_operand" "rI")))]
2338 [(set_attr "type" "unary")])
2342 (compare:CC (not:SI (match_operand:SI
0 "arith_operand" "rI"))
2345 "xnorcc %%g0,%
0,%%g0"
2346 [(set_attr "type" "compare")])
2350 (compare:CC (not:SI (match_operand:SI
1 "arith_operand" "rI"))
2352 (set (match_operand:SI
0 "register_operand" "=r")
2353 (not:SI (match_dup
1)))]
2356 [(set_attr "type" "unary")])
2358 ;; Floating point arithmetic instructions.
2360 (define_insn "addtf3"
2361 [(set (match_operand:TF
0 "register_operand" "=f")
2362 (plus:TF (match_operand:TF
1 "register_operand" "f")
2363 (match_operand:TF
2 "register_operand" "f")))]
2366 [(set_attr "type" "fp")])
2368 (define_insn "adddf3"
2369 [(set (match_operand:DF
0 "register_operand" "=f")
2370 (plus:DF (match_operand:DF
1 "register_operand" "f")
2371 (match_operand:DF
2 "register_operand" "f")))]
2374 [(set_attr "type" "fp")])
2376 (define_insn "addsf3"
2377 [(set (match_operand:SF
0 "register_operand" "=f")
2378 (plus:SF (match_operand:SF
1 "register_operand" "f")
2379 (match_operand:SF
2 "register_operand" "f")))]
2382 [(set_attr "type" "fp")])
2384 (define_insn "subtf3"
2385 [(set (match_operand:TF
0 "register_operand" "=f")
2386 (minus:TF (match_operand:TF
1 "register_operand" "f")
2387 (match_operand:TF
2 "register_operand" "f")))]
2390 [(set_attr "type" "fp")])
2392 (define_insn "subdf3"
2393 [(set (match_operand:DF
0 "register_operand" "=f")
2394 (minus:DF (match_operand:DF
1 "register_operand" "f")
2395 (match_operand:DF
2 "register_operand" "f")))]
2398 [(set_attr "type" "fp")])
2400 (define_insn "subsf3"
2401 [(set (match_operand:SF
0 "register_operand" "=f")
2402 (minus:SF (match_operand:SF
1 "register_operand" "f")
2403 (match_operand:SF
2 "register_operand" "f")))]
2406 [(set_attr "type" "fp")])
2408 (define_insn "multf3"
2409 [(set (match_operand:TF
0 "register_operand" "=f")
2410 (mult:TF (match_operand:TF
1 "register_operand" "f")
2411 (match_operand:TF
2 "register_operand" "f")))]
2414 [(set_attr "type" "fpmul")])
2416 (define_insn "muldf3"
2417 [(set (match_operand:DF
0 "register_operand" "=f")
2418 (mult:DF (match_operand:DF
1 "register_operand" "f")
2419 (match_operand:DF
2 "register_operand" "f")))]
2422 [(set_attr "type" "fpmul")])
2424 (define_insn "mulsf3"
2425 [(set (match_operand:SF
0 "register_operand" "=f")
2426 (mult:SF (match_operand:SF
1 "register_operand" "f")
2427 (match_operand:SF
2 "register_operand" "f")))]
2430 [(set_attr "type" "fpmul")])
2432 (define_insn "divtf3"
2433 [(set (match_operand:TF
0 "register_operand" "=f")
2434 (div:TF (match_operand:TF
1 "register_operand" "f")
2435 (match_operand:TF
2 "register_operand" "f")))]
2438 [(set_attr "type" "fpdiv")])
2440 (define_insn "divdf3"
2441 [(set (match_operand:DF
0 "register_operand" "=f")
2442 (div:DF (match_operand:DF
1 "register_operand" "f")
2443 (match_operand:DF
2 "register_operand" "f")))]
2446 [(set_attr "type" "fpdiv")])
2448 (define_insn "divsf3"
2449 [(set (match_operand:SF
0 "register_operand" "=f")
2450 (div:SF (match_operand:SF
1 "register_operand" "f")
2451 (match_operand:SF
2 "register_operand" "f")))]
2454 [(set_attr "type" "fpdiv")])
2456 (define_insn "negtf2"
2457 [(set (match_operand:TF
0 "register_operand" "=f,f")
2458 (neg:TF (match_operand:TF
1 "register_operand" "
0,f")))]
2462 fnegs %
1,%
0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2463 [(set_attr "type" "fp")
2464 (set_attr "length" "
1,
4")])
2466 (define_insn "negdf2"
2467 [(set (match_operand:DF
0 "register_operand" "=f,f")
2468 (neg:DF (match_operand:DF
1 "register_operand" "
0,f")))]
2472 fnegs %
1,%
0\;fmovs %R1,%R0"
2473 [(set_attr "type" "fp")
2474 (set_attr "length" "
1,
2")])
2476 (define_insn "negsf2"
2477 [(set (match_operand:SF
0 "register_operand" "=f")
2478 (neg:SF (match_operand:SF
1 "register_operand" "f")))]
2481 [(set_attr "type" "fp")])
2483 (define_insn "abstf2"
2484 [(set (match_operand:TF
0 "register_operand" "=f,f")
2485 (abs:TF (match_operand:TF
1 "register_operand" "
0,f")))]
2489 fabss %
1,%
0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2490 [(set_attr "type" "fp")
2491 (set_attr "length" "
1,
4")])
2493 (define_insn "absdf2"
2494 [(set (match_operand:DF
0 "register_operand" "=f,f")
2495 (abs:DF (match_operand:DF
1 "register_operand" "
0,f")))]
2499 fabss %
1,%
0\;fmovs %R1,%R0"
2500 [(set_attr "type" "fp")
2501 (set_attr "length" "
1,
2")])
2503 (define_insn "abssf2"
2504 [(set (match_operand:SF
0 "register_operand" "=f")
2505 (abs:SF (match_operand:SF
1 "register_operand" "f")))]
2508 [(set_attr "type" "fp")])
2510 (define_insn "sqrttf2"
2511 [(set (match_operand:TF
0 "register_operand" "=f")
2512 (sqrt:TF (match_operand:TF
1 "register_operand" "f")))]
2515 [(set_attr "type" "fpsqrt")])
2517 (define_insn "sqrtdf2"
2518 [(set (match_operand:DF
0 "register_operand" "=f")
2519 (sqrt:DF (match_operand:DF
1 "register_operand" "f")))]
2522 [(set_attr "type" "fpsqrt")])
2524 (define_insn "sqrtsf2"
2525 [(set (match_operand:SF
0 "register_operand" "=f")
2526 (sqrt:SF (match_operand:SF
1 "register_operand" "f")))]
2529 [(set_attr "type" "fpsqrt")])
2531 ;;- arithmetic shift instructions
2533 ;; We can trivially handle shifting the constant
1 by
64 bits.
2534 ;; For other shifts we use the library routine.
2535 ;; ??? Questionable, we can do better than this can't we?
2536 (define_expand "ashldi3"
2537 [(parallel [(set (match_operand:DI
0 "register_operand" "")
2538 (ashift:DI (match_operand:DI
1 "const_double_operand" "")
2539 (match_operand:SI
2 "register_operand" "")))
2540 (clobber (reg:SI
0))])]
2544 if (GET_CODE (operands[
1]) == CONST_DOUBLE
2545 && CONST_DOUBLE_HIGH (operands[
1]) ==
0
2546 && CONST_DOUBLE_LOW (operands[
1]) ==
1)
2547 operands[
1] = const1_rtx;
2548 else if (operands[
1] != const1_rtx)
2552 ;; ??? Questionable, we can do better than this can't we?
2554 [(set (match_operand:DI
0 "register_operand" "=&r")
2555 (ashift:DI (const_int
1)
2556 (match_operand:SI
1 "register_operand" "r")))
2557 (clobber (reg:SI
0))]
2559 "subcc %
1,
32,%%g0\;addx %%g0,
0,%R0\;xor %R0,
1,%
0\;sll %R0,%
1,%R0\;sll %
0,%
1,%
0"
2560 [(set_attr "type" "multi")
2561 (set_attr "length" "
5")])
2563 (define_insn "ashlsi3"
2564 [(set (match_operand:SI
0 "register_operand" "=r")
2565 (ashift:SI (match_operand:SI
1 "register_operand" "r")
2566 (match_operand:SI
2 "arith_operand" "rI")))]
2570 (define_insn "ashrsi3"
2571 [(set (match_operand:SI
0 "register_operand" "=r")
2572 (ashiftrt:SI (match_operand:SI
1 "register_operand" "r")
2573 (match_operand:SI
2 "arith_operand" "rI")))]
2577 (define_insn "lshrsi3"
2578 [(set (match_operand:SI
0 "register_operand" "=r")
2579 (lshiftrt:SI (match_operand:SI
1 "register_operand" "r")
2580 (match_operand:SI
2 "arith_operand" "rI")))]
2584 ;; Unconditional and other jump instructions
2585 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
2586 ;; following insn is never executed. This saves us a nop. Dbx does not
2587 ;; handle such branches though, so we only use them when optimizing.
2589 [(set (pc) (label_ref (match_operand
0 "" "")))]
2592 [(set_attr "type" "uncond_branch")])
2594 (define_expand "tablejump"
2595 [(parallel [(set (pc) (match_operand:SI
0 "register_operand" "r"))
2596 (use (label_ref (match_operand
1 "" "")))])]
2600 /* We need to use the PC value in %o7 that was set up when the address
2601 of the label was loaded into a register, so we need different RTL. */
2604 emit_insn (gen_pic_tablejump (operands[
0], operands[
1]));
2609 (define_insn "pic_tablejump"
2610 [(set (pc) (match_operand:SI
0 "register_operand" "r"))
2611 (use (label_ref (match_operand
1 "" "")))
2615 [(set_attr "type" "uncond_branch")])
2618 [(set (pc) (match_operand:SI
0 "address_operand" "p"))
2619 (use (label_ref (match_operand
1 "" "")))]
2622 [(set_attr "type" "uncond_branch")])
2625 [(set (pc) (label_ref (match_operand
0 "" "")))
2626 (set (reg:SI
15) (label_ref (match_dup
0)))]
2629 [(set_attr "type" "uncond_branch")])
2631 ;; This pattern recognizes the "instruction" that appears in
2632 ;; a function call that wants a structure value,
2633 ;; to inform the called function if compiled with Sun CC.
2635 ; [(match_operand:SI
0 "immediate_operand" "")]
2636 ; "GET_CODE (operands[
0]) == CONST_INT && INTVAL (operands[
0]) >
0"
2638 ; [(set_attr "type" "marker")])
2640 ;;- jump to subroutine
2641 (define_expand "call"
2642 ;; Note that this expression is not used for generating RTL.
2643 ;; All the RTL is generated explicitly below.
2644 [(call (match_operand:SI
0 "call_operand" "")
2645 (match_operand
3 "" "i"))]
2646 ;; operands[
2] is next_arg_register
2647 ;; operands[
3] is struct_value_size_rtx.
2651 rtx fn_rtx, nregs_rtx;
2653 if (GET_CODE (XEXP (operands[
0],
0)) == LABEL_REF)
2655 /* This is really a PIC sequence. We want to represent
2656 it as a funny jump so it's delay slots can be filled.
2658 ??? But if this really *is* a CALL, will not it clobber the
2659 call-clobbered registers? We lose this if it is a JUMP_INSN.
2660 Why cannot we have delay slots filled if it were a CALL? */
2662 if (INTVAL (operands[
3]) >
0)
2663 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (
3,
2664 gen_rtx (SET, VOIDmode, pc_rtx,
2665 XEXP (operands[
0],
0)),
2667 gen_rtx (CLOBBER, VOIDmode,
2668 gen_rtx (REG, SImode,
15)))));
2670 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (
2,
2671 gen_rtx (SET, VOIDmode, pc_rtx,
2672 XEXP (operands[
0],
0)),
2673 gen_rtx (CLOBBER, VOIDmode,
2674 gen_rtx (REG, SImode,
15)))));
2678 fn_rtx = operands[
0];
2680 /* Count the number of parameter registers being used by this call.
2681 if that argument is NULL, it means we are using them all, which
2682 means
6 on the sparc. */
2685 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[
2]) -
8);
2687 nregs_rtx = gen_rtx (CONST_INT, VOIDmode,
6);
2689 nregs_rtx = const0_rtx;
2692 if (INTVAL (operands[
3]) >
0)
2693 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (
3,
2694 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2696 gen_rtx (CLOBBER, VOIDmode,
2697 gen_rtx (REG, SImode,
15)))));
2699 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (
2,
2700 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2701 gen_rtx (CLOBBER, VOIDmode,
2702 gen_rtx (REG, SImode,
15)))));
2706 /* If this call wants a structure value,
2707 emit an unimp insn to let the called function know about this. */
2708 if (INTVAL (operands[
3]) >
0)
2710 rtx insn = emit_insn (operands[
3]);
2711 SCHED_GROUP_P (insn) =
1;
2719 [(call (mem:SI (match_operand:SI
0 "call_operand_address" "S,r"))
2720 (match_operand
1 "" ""))
2721 (clobber (reg:SI
15))]
2722 ;;- Do not use operand
1 for most machines.
2726 return
\"call %a0,%
1%#
\";
2728 [(set_attr "type" "call")])
2730 ;; This is a call that wants a structure value.
2732 [(call (mem:SI (match_operand:SI
0 "call_operand_address" "S,r"))
2733 (match_operand
1 "" ""))
2734 (match_operand
2 "immediate_operand" "")
2735 (clobber (reg:SI
15))]
2736 ;;- Do not use operand
1 for most machines.
2737 "GET_CODE (operands[
2]) == CONST_INT && INTVAL (operands[
2]) >
0"
2740 return
\"call %a0,%
1\;nop\;unimp %
2\";
2742 [(set_attr "type" "call_no_delay_slot")])
2744 (define_expand "call_value"
2745 [(set (match_operand
0 "register_operand" "=rf")
2746 (call (match_operand:SI
1 "" "")
2747 (match_operand
4 "" "")))]
2748 ;; operand
3 is next_arg_register
2752 rtx fn_rtx, nregs_rtx;
2755 fn_rtx = operands[
1];
2759 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[
3]) -
8);
2761 nregs_rtx = gen_rtx (CONST_INT, VOIDmode,
6);
2763 nregs_rtx = const0_rtx;
2767 gen_rtx (SET, VOIDmode, operands[
0],
2768 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2769 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode,
15)));
2771 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2777 [(set (match_operand
0 "" "=rf")
2778 (call (mem:SI (match_operand:SI
1 "call_operand_address" "rS"))
2779 (match_operand
2 "" "")))
2780 (clobber (reg:SI
15))]
2781 ;;- Do not use operand
2 for most machines.
2785 return
\"call %a1,%
2%#
\";
2787 [(set_attr "type" "call")])
2789 (define_insn "return"
2792 "* return output_return (operands);"
2793 [(set_attr "type" "multi")])
2800 (define_insn "indirect_jump"
2801 [(set (pc) (match_operand:SI
0 "address_operand" "p"))]
2804 [(set_attr "type" "uncond_branch")])
2806 (define_expand "nonlocal_goto"
2807 [(match_operand:SI
0 "general_operand" "")
2808 (match_operand:SI
1 "general_operand" "")
2809 (match_operand:SI
2 "general_operand" "")
2810 (match_operand:SI
3 "" "")]
2815 /* Trap instruction to flush all the registers window. */
2816 emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2817 gen_rtvec (
1, const0_rtx),
0));
2818 /* Load the fp value for the containing fn into %fp.
2819 This is needed because operands[
2] refers to %fp. */
2820 emit_move_insn (virtual_stack_vars_rtx, operands[
0]);
2821 /* Find the containing function's current nonlocal goto handler,
2822 which will do any cleanups and then jump to the label. */
2823 emit_move_insn (gen_rtx (REG, SImode,
8), operands[
1]);
2824 /* Restore %fp from stack pointer value for containing function.
2825 The restore insn that follows will move this to %sp,
2826 and reload the appropriate value into %fp. */
2827 emit_move_insn (frame_pointer_rtx, operands[
2]);
2828 /* Put in the static chain register the nonlocal label address. */
2829 emit_move_insn (static_chain_rtx, operands[
3]);
2830 /* USE of frame_pointer_rtx added for consistency; not clear if
2832 emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
2833 emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
2834 emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
2835 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode,
8)));
2836 /* Return, restoring reg window and jumping to goto handler. */
2837 emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2838 gen_rtvec (
1, const0_rtx),
1));
2842 ;; Special trap insn to flush register windows.
2844 [(unspec_volatile [(const_int
0)]
0)]
2847 [(set_attr "type" "misc")])
2850 [(unspec_volatile [(const_int
0)]
1)]
2852 "jmp %%o0+
0\;restore"
2853 [(set_attr "type" "misc")
2854 (set_attr "length" "
2")])
2856 ;; Split up troublesome insns for better scheduling. */
2858 ;; The following patterns are straightforward. They can be applied
2859 ;; either before or after register allocation.
2862 [(set (match_operator
0 "memop" [(match_operand:SI
1 "symbolic_operand" "")])
2863 (match_operand
2 "reg_or_0_operand" ""))
2864 (clobber (match_operand:SI
3 "register_operand" ""))]
2866 [(set (match_dup
3) (high:SI (match_dup
1)))
2867 (set (match_op_dup
0 [(lo_sum:SI (match_dup
3) (match_dup
1))])
2872 [(set (match_operator
0 "memop"
2873 [(match_operand:SI
1 "immediate_operand" "")])
2874 (match_operand
2 "general_operand" ""))
2875 (clobber (match_operand:SI
3 "register_operand" ""))]
2877 [(set (match_op_dup
0 [(match_dup
1)])
2881 operands[
1] = legitimize_pic_address (operands[
1], GET_MODE (operands[
0]),
2886 [(set (match_operand
0 "register_operand" "")
2887 (match_operator
1 "memop"
2888 [(match_operand:SI
2 "immediate_operand" "")]))]
2891 (match_op_dup
1 [(match_dup
2)]))]
2894 operands[
2] = legitimize_pic_address (operands[
2], GET_MODE (operands[
1]),
2898 ;; Sign- and Zero-extend operations can have symbolic memory operands.
2901 [(set (match_operand
0 "register_operand" "")
2902 (match_operator
1 "extend_op"
2903 [(match_operator
2 "memop"
2904 [(match_operand:SI
3 "immediate_operand" "")])]))]
2907 (match_op_dup
1 [(match_op_dup
2 [(match_dup
3)])]))]
2910 operands[
3] = legitimize_pic_address (operands[
3], GET_MODE (operands[
2]),
2915 [(set (match_operand:SI
0 "register_operand" "")
2916 (match_operand:SI
1 "immediate_operand" ""))]
2917 "! flag_pic && (GET_CODE (operands[
1]) == SYMBOL_REF
2918 || GET_CODE (operands[
1]) == CONST
2919 || GET_CODE (operands[
1]) == LABEL_REF)"
2920 [(set (match_dup
0) (high:SI (match_dup
1)))
2922 (lo_sum:SI (match_dup
0) (match_dup
1)))]
2925 ;; LABEL_REFs are not modified by
`legitimize_pic_address`
2926 ;; so do not recurse infinitely in the PIC case.
2928 [(set (match_operand:SI
0 "register_operand" "")
2929 (match_operand:SI
1 "immediate_operand" ""))]
2930 "flag_pic && (GET_CODE (operands[
1]) == SYMBOL_REF
2931 || GET_CODE (operands[
1]) == CONST)"
2932 [(set (match_dup
0) (match_dup
1))]
2935 operands[
1] = legitimize_pic_address (operands[
1], Pmode, operands[
0],
0);
2938 ;; These split sne/seq insns. The forms of the resulting insns are
2939 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
2940 ;; Nothing will look at these in detail after splitting has occurred.
2943 [(set (match_operand:SI
0 "register_operand" "")
2944 (ne:SI (match_operand:SI
1 "register_operand" "") (const_int
0)))
2945 (clobber (reg:CC
0))]
2947 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
2949 (set (match_dup
0) (ltu:SI (reg:CC
0) (const_int
0)))]
2953 [(set (match_operand:SI
0 "register_operand" "")
2954 (neg:SI (ne:SI (match_operand:SI
1 "register_operand" "")
2956 (clobber (reg:CC
0))]
2958 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
2960 (set (match_dup
0) (neg:SI (ltu:SI (reg:CC
0) (const_int
0))))]
2964 [(set (match_operand:SI
0 "register_operand" "")
2965 (eq:SI (match_operand:SI
1 "register_operand" "") (const_int
0)))
2966 (clobber (reg:CC
0))]
2968 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
2970 (set (match_dup
0) (geu:SI (reg:CC
0) (const_int
0)))]
2974 [(set (match_operand:SI
0 "register_operand" "")
2975 (neg:SI (eq:SI (match_operand:SI
1 "register_operand" "")
2977 (clobber (reg:CC
0))]
2979 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
2981 (set (match_dup
0) (neg:SI (geu:SI (reg:CC
0) (const_int
0))))]
2985 [(set (match_operand:SI
0 "register_operand" "")
2986 (plus:SI (ne:SI (match_operand:SI
1 "register_operand" "")
2988 (match_operand:SI
2 "register_operand" "")))
2989 (clobber (reg:CC
0))]
2991 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
2993 (set (match_dup
0) (plus:SI (ltu:SI (reg:CC
0) (const_int
0))
2998 [(set (match_operand:SI
0 "register_operand" "")
2999 (minus:SI (match_operand:SI
2 "register_operand" "")
3000 (ne:SI (match_operand:SI
1 "register_operand" "")
3002 (clobber (reg:CC
0))]
3004 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
3006 (set (match_dup
0) (minus:SI (match_dup
2)
3007 (ltu:SI (reg:CC
0) (const_int
0))))]
3011 [(set (match_operand:SI
0 "register_operand" "")
3012 (plus:SI (eq:SI (match_operand:SI
1 "register_operand" "")
3014 (match_operand:SI
2 "register_operand" "")))
3015 (clobber (reg:CC
0))]
3017 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
3019 (set (match_dup
0) (plus:SI (geu:SI (reg:CC
0) (const_int
0))
3024 [(set (match_operand:SI
0 "register_operand" "")
3025 (minus:SI (match_operand:SI
2 "register_operand" "")
3026 (eq:SI (match_operand:SI
1 "register_operand" "")
3028 (clobber (reg:CC
0))]
3030 [(set (reg:CC_NOOV
0) (compare:CC_NOOV (neg:SI (match_dup
1))
3032 (set (match_dup
0) (minus:SI (match_dup
2)
3033 (geu:SI (reg:CC
0) (const_int
0))))]
3036 ;; Peepholes go at the end.
3038 ;; Optimize consecutive loads or stores into ldd and std when possible.
3039 ;; The conditions in which we do this are very restricted and are
3040 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
3043 [(set (match_operand:SI
0 "register_operand" "=r")
3044 (match_operand:SI
1 "memory_operand" ""))
3045 (set (match_operand:SI
2 "register_operand" "=r")
3046 (match_operand:SI
3 "memory_operand" ""))]
3047 "registers_ok_for_ldd_peep (operands[
0], operands[
2])
3048 && ! MEM_VOLATILE_P (operands[
1]) && ! MEM_VOLATILE_P (operands[
3])
3049 && addrs_ok_for_ldd_peep (XEXP (operands[
1],
0), XEXP (operands[
3],
0))"
3053 [(set (match_operand:SI
0 "memory_operand" "")
3054 (match_operand:SI
1 "register_operand" "r"))
3055 (set (match_operand:SI
2 "memory_operand" "")
3056 (match_operand:SI
3 "register_operand" "r"))]
3057 "registers_ok_for_ldd_peep (operands[
1], operands[
3])
3058 && ! MEM_VOLATILE_P (operands[
0]) && ! MEM_VOLATILE_P (operands[
2])
3059 && addrs_ok_for_ldd_peep (XEXP (operands[
0],
0), XEXP (operands[
2],
0))"
3063 [(set (match_operand:SF
0 "register_operand" "=fr")
3064 (match_operand:SF
1 "memory_operand" ""))
3065 (set (match_operand:SF
2 "register_operand" "=fr")
3066 (match_operand:SF
3 "memory_operand" ""))]
3067 "registers_ok_for_ldd_peep (operands[
0], operands[
2])
3068 && ! MEM_VOLATILE_P (operands[
1]) && ! MEM_VOLATILE_P (operands[
3])
3069 && addrs_ok_for_ldd_peep (XEXP (operands[
1],
0), XEXP (operands[
3],
0))"
3073 [(set (match_operand:SF
0 "memory_operand" "")
3074 (match_operand:SF
1 "register_operand" "fr"))
3075 (set (match_operand:SF
2 "memory_operand" "")
3076 (match_operand:SF
3 "register_operand" "fr"))]
3077 "registers_ok_for_ldd_peep (operands[
1], operands[
3])
3078 && ! MEM_VOLATILE_P (operands[
0]) && ! MEM_VOLATILE_P (operands[
2])
3079 && addrs_ok_for_ldd_peep (XEXP (operands[
0],
0), XEXP (operands[
2],
0))"
3083 [(set (match_operand:SI
0 "register_operand" "=r")
3084 (match_operand:SI
1 "memory_operand" ""))
3085 (set (match_operand:SI
2 "register_operand" "=r")
3086 (match_operand:SI
3 "memory_operand" ""))]
3087 "registers_ok_for_ldd_peep (operands[
2], operands[
0])
3088 && ! MEM_VOLATILE_P (operands[
3]) && ! MEM_VOLATILE_P (operands[
1])
3089 && addrs_ok_for_ldd_peep (XEXP (operands[
3],
0), XEXP (operands[
1],
0))"
3093 [(set (match_operand:SI
0 "memory_operand" "")
3094 (match_operand:SI
1 "register_operand" "r"))
3095 (set (match_operand:SI
2 "memory_operand" "")
3096 (match_operand:SI
3 "register_operand" "r"))]
3097 "registers_ok_for_ldd_peep (operands[
3], operands[
1])
3098 && ! MEM_VOLATILE_P (operands[
2]) && ! MEM_VOLATILE_P (operands[
0])
3099 && addrs_ok_for_ldd_peep (XEXP (operands[
2],
0), XEXP (operands[
0],
0))"
3103 [(set (match_operand:SF
0 "register_operand" "=fr")
3104 (match_operand:SF
1 "memory_operand" ""))
3105 (set (match_operand:SF
2 "register_operand" "=fr")
3106 (match_operand:SF
3 "memory_operand" ""))]
3107 "registers_ok_for_ldd_peep (operands[
2], operands[
0])
3108 && ! MEM_VOLATILE_P (operands[
3]) && ! MEM_VOLATILE_P (operands[
1])
3109 && addrs_ok_for_ldd_peep (XEXP (operands[
3],
0), XEXP (operands[
1],
0))"
3113 [(set (match_operand:SF
0 "memory_operand" "")
3114 (match_operand:SF
1 "register_operand" "fr"))
3115 (set (match_operand:SF
2 "memory_operand" "")
3116 (match_operand:SF
3 "register_operand" "fr"))]
3117 "registers_ok_for_ldd_peep (operands[
3], operands[
1])
3118 && ! MEM_VOLATILE_P (operands[
2]) && ! MEM_VOLATILE_P (operands[
0])
3119 && addrs_ok_for_ldd_peep (XEXP (operands[
2],
0), XEXP (operands[
0],
0))"
3122 ;; Optimize the case of following a reg-reg move with a test
3123 ;; of reg just moved.
3126 [(set (match_operand:SI
0 "register_operand" "=r")
3127 (match_operand:SI
1 "register_operand" "r"))
3129 (compare:CC (match_operand:SI
2 "register_operand" "r")
3131 "rtx_equal_p (operands[
2], operands[
0])
3132 || rtx_equal_p (operands[
2], operands[
1])"
3135 ;; Do {sign,zero}-extended compares somewhat more efficiently.
3136 ;; ??? Is this now the Right Way to do this? Or will SCRATCH
3137 ;; eventually have some impact here?
3140 [(set (match_operand:HI
0 "register_operand" "")
3141 (match_operand:HI
1 "memory_operand" ""))
3142 (set (match_operand:SI
2 "register_operand" "")
3143 (sign_extend:SI (match_dup
0)))
3145 (compare:CC (match_dup
2)
3148 "ldsh %
1,%
0\;orcc %
0,%%g0,%
2")
3151 [(set (match_operand:QI
0 "register_operand" "")
3152 (match_operand:QI
1 "memory_operand" ""))
3153 (set (match_operand:SI
2 "register_operand" "")
3154 (sign_extend:SI (match_dup
0)))
3156 (compare:CC (match_dup
2)
3159 "ldsb %
1,%
0\;orcc %
0,%%g0,%
2")
3162 [(set (match_operand:HI
0 "register_operand" "")
3163 (match_operand:HI
1 "memory_operand" ""))
3164 (set (match_operand:SI
2 "register_operand" "")
3165 (sign_extend:SI (match_dup
0)))]
3166 "dead_or_set_p (insn, operands[
0])"
3169 warning (
\"bad peephole
\");
3170 if (! MEM_VOLATILE_P (operands[
1]))
3172 return
\"ldsh %
1,%
2\";
3176 [(set (match_operand:QI
0 "register_operand" "")
3177 (match_operand:QI
1 "memory_operand" ""))
3178 (set (match_operand:SI
2 "register_operand" "")
3179 (sign_extend:SI (match_dup
0)))]
3180 "dead_or_set_p (insn, operands[
0])"
3183 warning (
\"bad peephole
\");
3184 if (! MEM_VOLATILE_P (operands[
1]))
3186 return
\"ldsb %
1,%
2\";
3189 ;; Floating-point move peepholes
3192 [(set (match_operand:SI
0 "register_operand" "=r")
3193 (lo_sum:SI (match_dup
0)
3194 (match_operand:SI
1 "immediate_operand" "i")))
3195 (set (match_operand:DF
2 "register_operand" "=fr")
3196 (mem:DF (match_dup
0)))]
3197 "RTX_UNCHANGING_P (operands[
1]) && reg_unused_after (operands[
0], insn)"
3200 /* Go by way of output_move_double in case the register in operand
2
3201 is not properly aligned for ldd. */
3202 operands[
1] = gen_rtx (MEM, DFmode,
3203 gen_rtx (LO_SUM, SImode, operands[
0], operands[
1]));
3204 operands[
0] = operands[
2];
3205 return output_move_double (operands);
3209 [(set (match_operand:SI
0 "register_operand" "=r")
3210 (lo_sum:SI (match_dup
0)
3211 (match_operand:SI
1 "immediate_operand" "i")))
3212 (set (match_operand:SF
2 "register_operand" "=fr")
3213 (mem:SF (match_dup
0)))]
3214 "RTX_UNCHANGING_P (operands[
1]) && reg_unused_after (operands[
0], insn)"
3215 "ld [%
0+%%lo(%a1)],%
2")
3217 ;; Return peepholes. First the "normal" ones
3220 [(set (match_operand:SI
0 "restore_operand" "")
3221 (match_operand:SI
1 "arith_operand" "rI"))
3226 if (current_function_returns_struct)
3227 return
\"jmp %%i7+
12\;restore %%g0,%
1,%Y0
\";
3229 return
\"ret\;restore %%g0,%
1,%Y0
\";
3231 [(set_attr "type" "multi")])
3234 [(set (match_operand:SI
0 "restore_operand" "")
3235 (plus:SI (match_operand:SI
1 "arith_operand" "%r")
3236 (match_operand:SI
2 "arith_operand" "rI")))
3241 if (current_function_returns_struct)
3242 return
\"jmp %%i7+
12\;restore %r1,%
2,%Y0
\";
3244 return
\"ret\;restore %r1,%
2,%Y0
\";
3246 [(set_attr "type" "multi")])
3248 ;; Turned off because it should never match (subtracting a constant
3249 ;; is turned into addition) and because it would do the wrong thing
3250 ;; when operand
2 is -
4096 (--
4096 ==
4096 is not a valid immediate).
3252 ;; [(set (match_operand:SI
0 "restore_operand" "")
3253 ;; (minus:SI (match_operand:SI
1 "register_operand" "r")
3254 ;; (match_operand:SI
2 "small_int" "I")))
3256 ;; "! TARGET_EPILOGUE"
3257 ;; "ret\;restore %
1,-(%
2),%Y0"
3258 ;; [(set_attr "type" "multi")])
3260 ;; The following pattern is only generated by delayed-branch scheduling,
3261 ;; when the insn winds up in the epilogue.
3264 (match_operand:SF
0 "register_operand" "f"))
3267 "ret\;fmovs %
0,%%f0"
3268 [(set_attr "type" "multi")])
3270 ;; Now peepholes to go a call followed by a jump.
3273 [(parallel [(set (match_operand
0 "" "")
3274 (call (mem:SI (match_operand:SI
1 "call_operand_address" "S,r"))
3275 (match_operand
2 "" "")))
3276 (clobber (reg:SI
15))])
3277 (set (pc) (label_ref (match_operand
3 "" "")))]
3278 "short_branch (INSN_UID (insn), INSN_UID (operands[
3]))"
3281 return
\"call %a1,%
2\;add %%o7,(%l3-.-
4),%%o7
\";
3285 [(parallel [(call (mem:SI (match_operand:SI
0 "call_operand_address" "S,r"))
3286 (match_operand
1 "" ""))
3287 (clobber (reg:SI
15))])
3288 (set (pc) (label_ref (match_operand
2 "" "")))]
3289 "short_branch (INSN_UID (insn), INSN_UID (operands[
2]))"
3292 return
\"call %a0,%
1\;add %%o7,(%l2-.-
4),%%o7
\";
3296 [(parallel [(set (match_operand:SI
0 "register_operand" "=r")
3297 (minus:SI (match_operand:SI
1 "reg_or_0_operand" "rJ")
3299 (clobber (reg:CC
0))])
3300 (set (reg:CC
0) (compare (match_dup
0) (const_int
0)))]
3304 ;;- Local variables:
3306 ;;- comment-start: ";;- "
3307 ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
3308 ;;- eval: (modify-syntax-entry ?[ "(]")
3309 ;;- eval: (modify-syntax-entry ?] ")[")
3310 ;;- eval: (modify-syntax-entry ?{ "(}")
3311 ;;- eval: (modify-syntax-entry ?} "){")