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,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" "move,unary")
60 (if_then_else (ior (match_operand 1 "arith_operand" "")
61 (match_operand 1 "arith_double_operand" ""))
62 (const_int 1) (const_int 2))]
66 (define_asm_attributes
67 [(set_attr "length" "1")
68 (set_attr "type" "multi")])
70 ;; Attributes for instruction and branch scheduling
72 (define_attr "in_call_delay" "false,true"
73 (cond [(eq_attr "type" "branch,call,call_no_delay_slot,multi")
74 (const_string "false")
75 (eq_attr "type" "load,fpload,store,fpstore")
76 (if_then_else (eq_attr "length" "1")
78 (const_string "false"))
79 (eq_attr "type" "address")
80 (if_then_else (eq_attr "use_clobbered" "false")
82 (const_string "false"))]
83 (if_then_else (eq_attr "length" "1")
85 (const_string "false"))))
87 (define_delay (eq_attr "type" "call")
88 [(eq_attr "in_call_delay" "true") (nil) (nil)])
90 ;; ??? Should implement the notion of predelay slots for floating point
91 ;; branches. This would allow us to remove the nop always inserted before
92 ;; a floating point branch.
94 (define_attr "in_branch_delay" "false,true"
95 (if_then_else (and (eq_attr "type" "!branch,call,call_no_delay_slot,multi")
96 (eq_attr "length" "1"))
98 (const_string "false")))
100 (define_delay (eq_attr "type" "branch")
101 [(eq_attr "in_branch_delay" "true")
102 (nil) (eq_attr "in_branch_delay" "true")])
104 ;; Function units of the SPARC
106 ;; (define_function_unit {name} {num-units} {n-users} {test}
107 ;; {ready-delay} {busy-delay} [{conflict-list}])
110 ;; (Noted only for documentation; units that take one cycle do not need to
113 ;; (define_function_unit "alu" 1 0
114 ;; (eq_attr "type" "unary,binary,move,address") 1 0)
116 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
117 (define_function_unit "memory" 1 0 (eq_attr "type" "load,fpload") 2 0)
119 ;; SPARC has two floating-point units: the FP ALU,
120 ;; and the FP MUL/DIV/SQRT unit.
121 ;; Instruction timings on the CY7C602 are as follows
135 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
136 ;; More insns cause the chip to stall. Until we handle this
137 ;; better in the scheduler, we use excess cycle times to
138 ;; more evenly spread out fp insns.
140 (define_function_unit "fp_alu" 1 2 (eq_attr "type" "fp") 8 0)
141 (define_function_unit "fp_mul" 1 2 (eq_attr "type" "fpmul") 10 0)
142 (define_function_unit "fp_div" 1 2 (eq_attr "type" "fpdiv") 23 0)
143 (define_function_unit "fp_sqrt" 1 2 (eq_attr "type" "fpsqrt") 34 0)
145 ;; Compare instructions.
146 ;; This controls RTL generation and register allocation.
148 ;; We generate RTL for comparisons and branches by having the cmpxx
149 ;; patterns store away the operands. Then, the scc and bcc patterns
150 ;; emit RTL for both the compare and the branch.
152 ;; We do this because we want to generate different code for an sne and
153 ;; seq insn. In those cases, if the second operand of the compare is not
154 ;; const0_rtx, we want to compute the xor of the two operands and test
157 ;; We start with the DEFINE_EXPANDs, then then DEFINE_INSNs to match
158 ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
159 ;; insns that actually require more than one machine instruction.
161 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
163 (define_expand "cmpsi"
165 (compare:CC (match_operand:SI 0 "register_operand" "")
166 (match_operand:SI 1 "arith_operand" "")))]
170 sparc_compare_op0 = operands[0];
171 sparc_compare_op1 = operands[1];
175 (define_expand "cmpsf"
177 (compare:CCFP (match_operand:SF 0 "register_operand" "")
178 (match_operand:SF 1 "register_operand" "")))]
182 sparc_compare_op0 = operands[0];
183 sparc_compare_op1 = operands[1];
187 (define_expand "cmpdf"
189 (compare:CCFP (match_operand:DF 0 "register_operand" "")
190 (match_operand:DF 1 "register_operand" "")))]
194 sparc_compare_op0 = operands[0];
195 sparc_compare_op1 = operands[1];
199 ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this
200 ;; without jumps using the addx/subx instructions. For the rest, we do
201 ;; branches. Seq_special and sne_special clobber the CC reg, because they
202 ;; generate addcc/subcc instructions.
204 (define_expand "seq_special"
205 [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
206 (match_operand:SI 2 "register_operand" "")))
207 (parallel [(set (match_operand:SI 0 "register_operand" "")
208 (eq:SI (match_dup 3) (const_int 0)))
209 (clobber (reg:CC 0))])]
212 "{ operands[3] = gen_reg_rtx (SImode); }")
214 (define_expand "sne_special"
215 [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "")
216 (match_operand:SI 2 "register_operand" "")))
217 (parallel [(set (match_operand:SI 0 "register_operand" "")
218 (ne:SI (match_dup 3) (const_int 0)))
219 (clobber (reg:CC 0))])]
221 "{ operands[3] = gen_reg_rtx (SImode); }")
224 [(set (match_operand:SI 0 "register_operand" "")
225 (eq:SI (match_dup 1) (const_int 0)))]
228 { if (GET_MODE (sparc_compare_op0) == SImode)
230 emit_insn (gen_seq_special (operands[0], sparc_compare_op0,
235 operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
239 [(set (match_operand:SI 0 "register_operand" "")
240 (ne:SI (match_dup 1) (const_int 0)))]
243 { if (GET_MODE (sparc_compare_op0) == SImode)
245 emit_insn (gen_sne_special (operands[0], sparc_compare_op0,
250 operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
254 [(set (match_operand:SI 0 "register_operand" "")
255 (gt:SI (match_dup 1) (const_int 0)))]
258 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
261 [(set (match_operand:SI 0 "register_operand" "")
262 (lt:SI (match_dup 1) (const_int 0)))]
265 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
268 [(set (match_operand:SI 0 "register_operand" "")
269 (ge:SI (match_dup 1) (const_int 0)))]
272 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
275 [(set (match_operand:SI 0 "register_operand" "")
276 (le:SI (match_dup 1) (const_int 0)))]
279 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
281 (define_expand "sgtu"
282 [(set (match_operand:SI 0 "register_operand" "")
283 (gtu:SI (match_dup 1) (const_int 0)))]
289 /* We can do ltu easily, so if both operands are registers, swap them and
291 if ((GET_CODE (sparc_compare_op0) == REG
292 || GET_CODE (sparc_compare_op0) == SUBREG)
293 && (GET_CODE (sparc_compare_op1) == REG
294 || GET_CODE (sparc_compare_op1) == SUBREG))
296 tem = sparc_compare_op0;
297 sparc_compare_op0 = sparc_compare_op1;
298 sparc_compare_op1 = tem;
299 emit_insn (gen_sltu (operands[0]));
303 operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
306 (define_expand "sltu"
307 [(set (match_operand:SI 0 "register_operand" "")
308 (ltu:SI (match_dup 1) (const_int 0)))]
311 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
314 (define_expand "sgeu"
315 [(set (match_operand:SI 0 "register_operand" "")
316 (geu:SI (match_dup 1) (const_int 0)))]
319 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
322 (define_expand "sleu"
323 [(set (match_operand:SI 0 "register_operand" "")
324 (leu:SI (match_dup 1) (const_int 0)))]
330 /* We can do geu easily, so if both operands are registers, swap them and
332 if ((GET_CODE (sparc_compare_op0) == REG
333 || GET_CODE (sparc_compare_op0) == SUBREG)
334 && (GET_CODE (sparc_compare_op1) == REG
335 || GET_CODE (sparc_compare_op1) == SUBREG))
337 tem = sparc_compare_op0;
338 sparc_compare_op0 = sparc_compare_op1;
339 sparc_compare_op1 = tem;
340 emit_insn (gen_sgeu (operands[0]));
344 operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
347 ;; Now the DEFINE_INSNs for the compare and scc cases. First the compares.
351 (compare:CC (match_operand:SI 0 "register_operand" "rJ")
352 (match_operand:SI 1 "arith_operand" "rI")))]
355 [(set_attr "type" "compare")])
359 (compare:CCFP (match_operand:DF 0 "register_operand" "f")
360 (match_operand:DF 1 "register_operand" "f")))]
363 [(set_attr "type" "fpcmp")])
367 (compare:CCFP (match_operand:SF 0 "register_operand" "f")
368 (match_operand:SF 1 "register_operand" "f")))]
371 [(set_attr "type" "fpcmp")])
373 ;; The SEQ and SNE patterns are special because they can be done
374 ;; without any branching and do not involve a COMPARE.
377 [(set (match_operand:SI 0 "register_operand" "=r")
378 (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
379 (clobber (reg:CC 0))]
381 "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
382 [(set_attr "type" "unary")
383 (set_attr "length" "2")])
386 [(set (match_operand:SI 0 "register_operand" "=r")
387 (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
389 (clobber (reg:CC 0))]
391 "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
392 [(set_attr "type" "unary")
393 (set_attr "length" "2")])
396 [(set (match_operand:SI 0 "register_operand" "=r")
397 (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))
398 (clobber (reg:CC 0))]
400 "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
401 [(set_attr "type" "unary")
402 (set_attr "length" "2")])
405 [(set (match_operand:SI 0 "register_operand" "=r")
406 (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
408 (clobber (reg:CC 0))]
410 "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
411 [(set_attr "type" "unary")
412 (set_attr "length" "2")])
414 ;; We can also do (x + (i == 0)) and related, so put them in.
417 [(set (match_operand:SI 0 "register_operand" "=r")
418 (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
420 (match_operand:SI 2 "register_operand" "r")))
421 (clobber (reg:CC 0))]
423 "subcc %%g0,%1,%%g0\;addx %2,0,%0"
424 [(set_attr "length" "2")])
427 [(set (match_operand:SI 0 "register_operand" "=r")
428 (minus:SI (match_operand:SI 2 "register_operand" "r")
429 (ne:SI (match_operand:SI 1 "register_operand" "r")
431 (clobber (reg:CC 0))]
433 "subcc %%g0,%1,%%g0\;subx %2,0,%0"
434 [(set_attr "length" "2")])
437 [(set (match_operand:SI 0 "register_operand" "=r")
438 (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
440 (match_operand:SI 2 "register_operand" "r")))
441 (clobber (reg:CC 0))]
443 "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
444 [(set_attr "length" "2")])
447 [(set (match_operand:SI 0 "register_operand" "=r")
448 (minus:SI (match_operand:SI 2 "register_operand" "r")
449 (eq:SI (match_operand:SI 1 "register_operand" "r")
451 (clobber (reg:CC 0))]
453 "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
454 [(set_attr "type" "unary")
455 (set_attr "length" "2")])
457 ;; We can also do GEU and LTU directly, but these operate after a
461 [(set (match_operand:SI 0 "register_operand" "=r")
462 (ltu:SI (reg:CC 0) (const_int 0)))]
465 [(set_attr "type" "misc")])
468 [(set (match_operand:SI 0 "register_operand" "=r")
469 (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
472 [(set_attr "type" "misc")])
474 ;; ??? Combine should canonicalize these next two to the same pattern.
476 [(set (match_operand:SI 0 "register_operand" "=r")
477 (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0)))
478 (match_operand:SI 1 "arith_operand" "rI")))]
481 [(set_attr "type" "unary")])
484 [(set (match_operand:SI 0 "register_operand" "=r")
485 (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
486 (match_operand:SI 1 "arith_operand" "rI"))))]
489 [(set_attr "type" "unary")])
492 [(set (match_operand:SI 0 "register_operand" "=r")
493 (geu:SI (reg:CC 0) (const_int 0)))]
496 [(set_attr "type" "misc")])
499 [(set (match_operand:SI 0 "register_operand" "=r")
500 (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
503 [(set_attr "type" "misc")])
505 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
508 [(set (match_operand:SI 0 "register_operand" "=r")
509 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
510 (match_operand:SI 1 "arith_operand" "rI")))]
513 [(set_attr "type" "unary")])
516 [(set (match_operand:SI 0 "register_operand" "=r")
517 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
518 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
519 (match_operand:SI 2 "arith_operand" "rI"))))]
522 [(set_attr "type" "binary")])
525 [(set (match_operand:SI 0 "register_operand" "=r")
526 (minus:SI (match_operand:SI 1 "register_operand" "r")
527 (ltu:SI (reg:CC 0) (const_int 0))))]
530 [(set_attr "type" "unary")])
532 ;; ??? Combine should canonicalize these next two to the same pattern.
534 [(set (match_operand:SI 0 "register_operand" "=r")
535 (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
536 (match_operand:SI 2 "arith_operand" "rI"))
537 (ltu:SI (reg:CC 0) (const_int 0))))]
540 [(set_attr "type" "binary")])
543 [(set (match_operand:SI 0 "register_operand" "=r")
544 (minus:SI (match_operand:SI 1 "register_operand" "r")
545 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
546 (match_operand:SI 2 "arith_operand" "rI"))))]
549 [(set_attr "type" "binary")])
552 [(set (match_operand:SI 0 "register_operand" "=r")
553 (plus:SI (geu:SI (reg:CC 0) (const_int 0))
554 (match_operand:SI 1 "register_operand" "r")))]
557 [(set_attr "type" "unary")])
560 [(set (match_operand:SI 0 "register_operand" "=r")
561 (minus:SI (match_operand:SI 1 "register_operand" "r")
562 (geu:SI (reg:CC 0) (const_int 0))))]
565 [(set_attr "type" "unary")])
567 ;; Now we have the generic scc insns. These will be done using a jump.
568 ;; We have to exclude the cases above, since we will not want combine to
569 ;; turn something that does not require a jump into something that does.
571 [(set (match_operand:SI 0 "register_operand" "=r")
572 (match_operator:SI 1 "normal_comp_operator" [(reg 0) (const_int 0)]))]
574 "* return output_scc_insn (operands, insn); "
575 [(set_attr "type" "multi")])
577 ;; These control RTL generation for conditional jump insns
581 (if_then_else (eq (match_dup 1) (const_int 0))
582 (label_ref (match_operand 0 "" ""))
586 { operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1); }")
590 (if_then_else (ne (match_dup 1) (const_int 0))
591 (label_ref (match_operand 0 "" ""))
595 { operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1); }")
599 (if_then_else (gt (match_dup 1) (const_int 0))
600 (label_ref (match_operand 0 "" ""))
604 { operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1); }")
606 (define_expand "bgtu"
608 (if_then_else (gtu (match_dup 1) (const_int 0))
609 (label_ref (match_operand 0 "" ""))
613 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
618 (if_then_else (lt (match_dup 1) (const_int 0))
619 (label_ref (match_operand 0 "" ""))
623 { operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1); }")
625 (define_expand "bltu"
627 (if_then_else (ltu (match_dup 1) (const_int 0))
628 (label_ref (match_operand 0 "" ""))
632 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
637 (if_then_else (ge (match_dup 1) (const_int 0))
638 (label_ref (match_operand 0 "" ""))
642 { operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1); }")
644 (define_expand "bgeu"
646 (if_then_else (geu (match_dup 1) (const_int 0))
647 (label_ref (match_operand 0 "" ""))
651 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
656 (if_then_else (le (match_dup 1) (const_int 0))
657 (label_ref (match_operand 0 "" ""))
661 { operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1); }")
663 (define_expand "bleu"
665 (if_then_else (leu (match_dup 1) (const_int 0))
666 (label_ref (match_operand 0 "" ""))
670 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
673 ;; Now match both normal and inverted jump.
677 (if_then_else (match_operator 0 "noov_compare_op"
678 [(reg 0) (const_int 0)])
679 (label_ref (match_operand 1 "" ""))
684 return output_cbranch (operands[0], 1, 0,
685 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
688 [(set_attr "type" "branch")])
692 (if_then_else (match_operator 0 "noov_compare_op"
693 [(reg 0) (const_int 0)])
695 (label_ref (match_operand 1 "" ""))))]
699 return output_cbranch (operands[0], 1, 1,
700 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
703 [(set_attr "type" "branch")])
707 (define_expand "movsi"
708 [(set (match_operand:SI 0 "general_operand" "")
709 (match_operand:SI 1 "general_operand" ""))]
713 if (emit_move_sequence (operands, SImode, 0))
717 (define_expand "reload_insi"
718 [(set (match_operand:SI 0 "register_operand" "=r")
719 (match_operand:SI 1 "general_operand" ""))
720 (clobber (match_operand:SI 2 "register_operand" "=&r"))]
724 if (emit_move_sequence (operands, SImode, operands[2]))
727 /* We don't want the clobber emitted, so handle this ourselves. */
728 emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
732 ;; We must support both 'r' and 'f' registers here, because combine may
733 ;; convert SFmode hard registers to SImode hard registers when simplifying
736 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
737 ;; problems with register allocation. Reload might try to put an interger
738 ;; in an fp register, or an fp number is an integer register.
741 [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,Q,Q,rf")
742 (match_operand:SI 1 "move_operand" "rI,K,Q,!Q,rJ,!f,!fr"))]
743 "register_operand (operands[0], SImode)
744 || register_operand (operands[1], SImode)
745 || operands[1] == const0_rtx"
753 st %r1,[%%fp-4]\;ld [%%fp-4],%0"
754 [(set_attr "type" "move,move,load,load,store,store,misc")
755 (set_attr "length" "*,1,*,*,*,*,2")])
757 ;; Special pic pattern, for loading the address of a label into a register.
758 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
762 [(set (match_operand:SI 0 "register_operand" "=r")
763 (match_operand:SI 1 "move_pic_label" "i"))
764 (set (reg:SI 15) (pc))]
766 "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
767 [(set_attr "type" "multi")
768 (set_attr "length" "4")])
771 [(set (match_operand:DI 0 "register_operand" "=r")
772 (high:DI (match_operand 1 "" "")))]
776 rtx op0 = operands[0];
777 rtx op1 = operands[1];
779 if (GET_CODE (op1) == CONST_INT)
781 operands[0] = operand_subword (op0, 1, 0, DImode);
782 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
784 operands[0] = operand_subword (op0, 0, 0, DImode);
785 if (INTVAL (op1) < 0)
786 output_asm_insn (\"mov -1,%0\", operands);
788 output_asm_insn (\"mov 0,%0\", operands);
790 else if (GET_CODE (op1) == CONST_DOUBLE)
792 operands[0] = operand_subword (op0, 1, 0, DImode);
793 operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
794 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
796 operands[0] = operand_subword (op0, 0, 0, DImode);
797 operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
798 output_asm_insn (singlemove_string (operands), operands);
803 [(set_attr "type" "move")
804 (set_attr "length" "2")])
807 [(set (match_operand:SI 0 "register_operand" "=r")
808 (high:SI (match_operand 1 "" "")))]
811 [(set_attr "type" "move")
812 (set_attr "length" "1")])
815 [(set (match_operand:HI 0 "register_operand" "=r")
816 (high:HI (match_operand 1 "" "")))]
819 [(set_attr "type" "move")
820 (set_attr "length" "1")])
823 [(set (match_operand:DI 0 "register_operand" "=r")
824 (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
825 (match_operand:DI 2 "immediate_operand" "in")))]
827 "or %R1,%%lo(%a2),%R0"
828 ;; Need to set length for this arith insn because operand2
829 ;; is not an "arith_operand".
830 [(set_attr "length" "1")])
833 [(set (match_operand:SI 0 "register_operand" "=r")
834 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
835 (match_operand:SI 2 "immediate_operand" "in")))]
838 ;; Need to set length for this arith insn because operand2
839 ;; is not an "arith_operand".
840 [(set_attr "length" "1")])
843 [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
844 (match_operand:SI 1 "reg_or_0_operand" "rJ"))
845 (clobber (match_scratch:SI 2 "=&r"))]
847 "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
848 [(set_attr "type" "store")
849 (set_attr "length" "2")])
851 (define_expand "movhi"
852 [(set (match_operand:HI 0 "general_operand" "")
853 (match_operand:HI 1 "general_operand" ""))]
857 if (emit_move_sequence (operands, HImode, 0))
862 [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
863 (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
864 "register_operand (operands[0], HImode)
865 || register_operand (operands[1], HImode)
866 || operands[1] == const0_rtx"
872 [(set_attr "type" "move,move,load,store")
873 (set_attr "length" "*,1,*,1")])
876 [(set (match_operand:HI 0 "register_operand" "=r")
877 (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
878 (match_operand 2 "immediate_operand" "in")))]
881 [(set_attr "length" "1")])
884 [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
885 (match_operand:HI 1 "reg_or_0_operand" "rJ"))
886 (clobber (match_scratch:SI 2 "=&r"))]
888 "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
889 [(set_attr "type" "store")
890 (set_attr "length" "2")])
892 (define_expand "movqi"
893 [(set (match_operand:QI 0 "general_operand" "")
894 (match_operand:QI 1 "general_operand" ""))]
898 if (emit_move_sequence (operands, QImode, 0))
903 [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
904 (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
905 "register_operand (operands[0], QImode)
906 || register_operand (operands[1], QImode)
907 || operands[1] == const0_rtx"
913 [(set_attr "type" "move,move,load,store")
914 (set_attr "length" "*,1,*,1")])
917 [(set (match_operand:QI 0 "register_operand" "=r")
918 (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
919 (match_operand 2 "immediate_operand" "in")) 0))]
922 [(set_attr "length" "1")])
925 [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
926 (match_operand:QI 1 "reg_or_0_operand" "rJ"))
927 (clobber (match_scratch:SI 2 "=&r"))]
929 "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
930 [(set_attr "type" "store")
931 (set_attr "length" "2")])
933 ;; The definition of this insn does not really explain what it does,
934 ;; but it should suffice
935 ;; that anything generated as this insn will be recognized as one
936 ;; and that it will not successfully combine with anything.
937 (define_expand "movstrsi"
938 [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
939 (mem:BLK (match_operand:BLK 1 "general_operand" "")))
940 (use (match_operand:SI 2 "arith32_operand" ""))
941 (use (match_operand:SI 3 "immediate_operand" ""))
942 (clobber (match_dup 0))
943 (clobber (match_dup 1))
944 (clobber (match_scratch:SI 4 ""))
946 (clobber (reg:SI 1))])]
950 if (GET_CODE (operands[2]) == CONST_INT
951 && GET_CODE (operands[3]) == CONST_INT
952 && INTVAL (operands[2]) / INTVAL (operands[3]) > 32)
955 operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
956 operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
957 operands[2] = force_not_mem (operands[2]);
961 [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
962 (mem:BLK (match_operand:SI 1 "register_operand" "r")))
963 (use (match_operand:SI 2 "arith32_operand" "rn"))
964 (use (match_operand:SI 3 "immediate_operand" "i"))
965 (clobber (match_dup 0))
966 (clobber (match_dup 1))
967 (clobber (match_scratch:SI 4 "=&r"))
969 (clobber (reg:SI 1))]
971 "* return output_block_move (operands);"
972 [(set_attr "type" "multi")])
974 ;; Floating point move insns
976 ;; This pattern forces (set (reg:DF ...) (const_double ...))
977 ;; to be reloaded by putting the constant into memory.
978 ;; It must come before the more general movdf pattern.
979 ;; ??? A similar pattern for SF mode values would also be useful, but it
980 ;; is not as easy to write.
982 [(set (match_operand:DF 0 "general_operand" "=?r,r,f,o")
983 (match_operand:DF 1 "" "?E,G,m,G"))]
984 "GET_CODE (operands[1]) == CONST_DOUBLE"
987 switch (which_alternative)
990 return output_move_double (operands);
992 return \"mov %%g0,%0\;mov %%g0,%R0\";
994 return output_fp_move_double (operands);
996 operands[1] = adj_offsettable_operand (operands[0], 4);
997 return \"st %%g0,%0\;st %%g0,%1\";
1000 [(set_attr "type" "load,move,fpload,store")
1001 (set_attr "length" "3,2,3,3")])
1003 (define_expand "movdf"
1004 [(set (match_operand:DF 0 "general_operand" "")
1005 (match_operand:DF 1 "general_operand" ""))]
1009 if (emit_move_sequence (operands, DFmode, 0))
1014 [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r,?f,?r")
1015 (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q,r,f"))]
1016 "register_operand (operands[0], DFmode)
1017 || register_operand (operands[1], DFmode)"
1020 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1021 return output_fp_move_double (operands);
1022 return output_move_double (operands);
1024 [(set_attr "type" "fp,move,fpstore,store,fpload,load,multi,multi")
1025 (set_attr "length" "2,2,3,3,3,3,3,3")])
1028 [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
1029 (match_operand:DF 1 "reg_or_0_operand" "rf,G"))
1030 (clobber (match_scratch:SI 2 "=&r,&r"))]
1034 output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1035 if (which_alternative == 0)
1036 return \"std %1,[%2+%%lo(%a0)]\";
1038 return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
1040 [(set_attr "type" "store")
1041 (set_attr "length" "3")])
1043 ;; Double-word move insns.
1045 (define_expand "movdi"
1046 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1047 (match_operand:DI 1 "general_operand" ""))]
1051 if (emit_move_sequence (operands, DImode, 0))
1056 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?f,?r,?Q")
1057 (match_operand:DI 1 "general_operand" "r,r,Q,i,r,f,Q,f,f"))]
1058 "register_operand (operands[0], DImode)
1059 || register_operand (operands[1], DImode)
1060 || operands[1] == const0_rtx"
1063 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1064 return output_fp_move_double (operands);
1065 return output_move_double (operands);
1067 [(set_attr "type" "move,store,load,misc,multi,fp,fpload,multi,fpstore")
1068 (set_attr "length" "2,3,3,3,3,2,3,3,3")])
1070 ;; Floating-point move insns.
1072 (define_expand "movsf"
1073 [(set (match_operand:SF 0 "general_operand" "")
1074 (match_operand:SF 1 "general_operand" ""))]
1078 if (emit_move_sequence (operands, SFmode, 0))
1083 [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,rf,f,r,Q,Q")
1084 (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,!rf,Q,Q,f,r"))]
1085 "register_operand (operands[0], SFmode)
1086 || register_operand (operands[1], SFmode)"
1090 st %r1,[%%fp-4]\;ld [%%fp-4],%0
1095 [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store")
1096 (set_attr "length" "*,*,2,*,*,*,*")])
1099 [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
1100 (match_operand:SF 1 "reg_or_0_operand" "rfG"))
1101 (clobber (match_scratch:SI 2 "=&r"))]
1103 "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1104 [(set_attr "type" "store")
1105 (set_attr "length" "2")])
1107 ;;- zero extension instructions
1109 ;; These patterns originally accepted general_operands, however, slightly
1110 ;; better code is generated by only accepting register_operands, and then
1111 ;; letting combine generate the ldu[hb] insns.
1113 (define_expand "zero_extendhisi2"
1114 [(set (match_operand:SI 0 "register_operand" "")
1115 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
1119 rtx temp = gen_reg_rtx (SImode);
1120 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1122 if (GET_CODE (operand1) == SUBREG)
1123 operand1 = XEXP (operand1, 0);
1125 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1127 emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
1132 [(set (match_operand:SI 0 "register_operand" "=r")
1133 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1136 [(set_attr "type" "load")])
1138 (define_expand "zero_extendqihi2"
1139 [(set (match_operand:HI 0 "register_operand" "")
1140 (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1145 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1146 (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1147 "GET_CODE (operands[1]) != CONST_INT"
1152 [(set_attr "type" "unary,move,load")
1153 (set_attr "length" "1")])
1155 (define_expand "zero_extendqisi2"
1156 [(set (match_operand:SI 0 "register_operand" "")
1157 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1162 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1163 (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,I,Q")))]
1164 "GET_CODE (operands[1]) != CONST_INT"
1169 [(set_attr "type" "unary,move,load")
1170 (set_attr "length" "1")])
1174 (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
1177 "andcc %0,0xff,%%g0"
1178 [(set_attr "type" "compare")])
1182 (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1184 (set (match_operand:SI 0 "register_operand" "=r")
1185 (zero_extend:SI (match_dup 1)))]
1188 [(set_attr "type" "unary")])
1190 ;;- sign extension instructions
1192 ;; These patterns originally accepted general_operands, however, slightly
1193 ;; better code is generated by only accepting register_operands, and then
1194 ;; letting combine generate the lds[hb] insns.
1196 (define_expand "extendhisi2"
1197 [(set (match_operand:SI 0 "register_operand" "")
1198 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1202 rtx temp = gen_reg_rtx (SImode);
1203 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1205 if (GET_CODE (operand1) == SUBREG)
1206 operand1 = XEXP (operand1, 0);
1208 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1210 emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
1215 [(set (match_operand:SI 0 "register_operand" "=r")
1216 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1219 [(set_attr "type" "load")])
1221 (define_expand "extendqihi2"
1222 [(set (match_operand:HI 0 "register_operand" "")
1223 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
1227 rtx temp = gen_reg_rtx (SImode);
1228 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1230 if (GET_CODE (operand1) == SUBREG)
1231 operand1 = XEXP (operand1, 0);
1232 if (GET_CODE (operand0) == SUBREG)
1233 operand0 = XEXP (operand0, 0);
1234 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1236 if (GET_MODE (operand0) != SImode)
1237 operand0 = gen_rtx (SUBREG, SImode, operand0, 0);
1238 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1243 [(set (match_operand:HI 0 "register_operand" "=r")
1244 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
1247 [(set_attr "type" "load")])
1249 (define_expand "extendqisi2"
1250 [(set (match_operand:SI 0 "register_operand" "")
1251 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
1255 rtx temp = gen_reg_rtx (SImode);
1256 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1258 if (GET_CODE (operand1) == SUBREG)
1259 operand1 = XEXP (operand1, 0);
1260 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1262 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1267 [(set (match_operand:SI 0 "register_operand" "=r")
1268 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1271 [(set_attr "type" "load")])
1273 ;; Conversions between float and double.
1275 (define_insn "extendsfdf2"
1276 [(set (match_operand:DF 0 "register_operand" "=f")
1278 (match_operand:SF 1 "register_operand" "f")))]
1281 [(set_attr "type" "fp")])
1283 (define_insn "truncdfsf2"
1284 [(set (match_operand:SF 0 "register_operand" "=f")
1286 (match_operand:DF 1 "register_operand" "f")))]
1289 [(set_attr "type" "fp")])
1291 ;; Conversion between fixed point and floating point.
1293 (define_insn "floatsisf2"
1294 [(set (match_operand:SF 0 "general_operand" "=f")
1295 (float:SF (match_operand:SI 1 "nonimmediate_operand" "rfm")))]
1297 "* return output_floatsisf2 (operands);"
1298 [(set_attr "type" "fp")
1299 (set_attr "length" "3")])
1301 (define_insn "floatsidf2"
1302 [(set (match_operand:DF 0 "general_operand" "=f")
1303 (float:DF (match_operand:SI 1 "nonimmediate_operand" "rfm")))]
1305 "* return output_floatsidf2 (operands);"
1306 [(set_attr "type" "fp")
1307 (set_attr "length" "3")])
1309 ;; Convert a float to an actual integer.
1310 ;; Truncation is performed as part of the conversion.
1312 (define_insn "fix_truncsfsi2"
1313 [(set (match_operand:SI 0 "general_operand" "=rm")
1314 (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))
1315 (clobber (match_scratch:SF 2 "=&f"))]
1319 if (FP_REG_P (operands[1]))
1320 output_asm_insn (\"fstoi %1,%2\", operands);
1322 output_asm_insn (\"ld %1,%2\;fstoi %2,%2\", operands);
1323 if (GET_CODE (operands[0]) == MEM)
1324 return \"st %2,%0\";
1326 return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\";
1328 [(set_attr "type" "fp")
1329 (set_attr "length" "3")])
1331 (define_insn "fix_truncdfsi2"
1332 [(set (match_operand:SI 0 "general_operand" "=rm")
1333 (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))
1334 (clobber (match_scratch:DF 2 "=&f"))]
1338 if (FP_REG_P (operands[1]))
1339 output_asm_insn (\"fdtoi %1,%2\", operands);
1343 xoperands[0] = operands[2];
1344 xoperands[1] = operands[1];
1345 output_asm_insn (output_fp_move_double (xoperands), xoperands);
1346 output_asm_insn (\"fdtoi %2,%2\", operands);
1348 if (GET_CODE (operands[0]) == MEM)
1349 return \"st %2,%0\";
1351 return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\";
1353 [(set_attr "type" "fp")
1354 (set_attr "length" "3")])
1356 ;;- arithmetic instructions
1358 (define_insn "adddi3"
1359 [(set (match_operand:DI 0 "register_operand" "=r")
1360 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
1361 (match_operand:DI 2 "arith_double_operand" "rHI")))
1362 (clobber (reg:SI 0))]
1366 rtx op2 = operands[2];
1368 /* If constant is postive, upper bits zeroed, otherwise unchanged
1369 * give the assembler a chance to pick the move instruction. */
1370 if (GET_CODE (op2) == CONST_INT)
1372 int sign = INTVAL (op2);
1374 return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1375 return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1377 else if (GET_CODE (op2) == CONST_DOUBLE)
1379 int sign = CONST_DOUBLE_HIGH (op2);
1380 operands[2] = gen_rtx (CONST_INT, VOIDmode,
1381 CONST_DOUBLE_LOW (operands[1]));
1383 return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1384 return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1386 return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
1388 [(set_attr "length" "2")])
1390 (define_insn "addsi3"
1391 [(set (match_operand:SI 0 "register_operand" "=r")
1392 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1393 (match_operand:SI 2 "arith_operand" "rI")))]
1398 [(set (reg:CC_NOOV 0)
1399 (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
1400 (match_operand:SI 1 "arith_operand" "rI"))
1404 [(set_attr "type" "compare")])
1407 [(set (reg:CC_NOOV 0)
1408 (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1409 (match_operand:SI 2 "arith_operand" "rI"))
1411 (set (match_operand:SI 0 "register_operand" "=r")
1412 (plus:SI (match_dup 1) (match_dup 2)))]
1416 (define_insn "subdi3"
1417 [(set (match_operand:DI 0 "register_operand" "=r")
1418 (minus:DI (match_operand:DI 1 "register_operand" "r")
1419 (match_operand:DI 2 "arith_double_operand" "rHI")))
1420 (clobber (reg:SI 0))]
1424 rtx op2 = operands[2];
1426 /* If constant is postive, upper bits zeroed, otherwise unchanged
1427 * give the assembler a chance to pick the move instruction. */
1428 if (GET_CODE (op2) == CONST_INT)
1430 int sign = INTVAL (op2);
1432 return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1433 return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1435 else if (GET_CODE (op2) == CONST_DOUBLE)
1437 int sign = CONST_DOUBLE_HIGH (op2);
1438 operands[2] = gen_rtx (CONST_INT, VOIDmode,
1439 CONST_DOUBLE_LOW (operands[1]));
1441 return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1442 return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1444 return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
1446 [(set_attr "length" "2")])
1448 (define_insn "subsi3"
1449 [(set (match_operand:SI 0 "register_operand" "=r")
1450 (minus:SI (match_operand:SI 1 "register_operand" "r")
1451 (match_operand:SI 2 "arith_operand" "rI")))]
1456 [(set (reg:CC_NOOV 0)
1457 (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
1458 (match_operand:SI 1 "arith_operand" "rI"))
1462 [(set_attr "type" "compare")])
1465 [(set (reg:CC_NOOV 0)
1466 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
1467 (match_operand:SI 2 "arith_operand" "rI"))
1469 (set (match_operand:SI 0 "register_operand" "=r")
1470 (minus:SI (match_dup 1) (match_dup 2)))]
1474 ;;- and instructions
1475 ;; We define DImode `and` so with DImode `not` we can get
1476 ;; DImode `andn`. Other combinations are possible.
1478 (define_expand "anddi3"
1479 [(set (match_operand:DI 0 "register_operand" "")
1480 (and:DI (match_operand:DI 1 "arith_double_operand" "")
1481 (match_operand:DI 2 "arith_double_operand" "")))]
1486 [(set (match_operand:DI 0 "register_operand" "=r")
1487 (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
1488 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1492 rtx op2 = operands[2];
1494 /* If constant is postive, upper bits zeroed, otherwise unchanged
1495 * give the assembler a chance to pick the move instruction. */
1496 if (GET_CODE (op2) == CONST_INT)
1498 int sign = INTVAL (op2);
1500 return \"mov %1,%0\;and %R1,%2,%R0\";
1501 return \"mov 0,%0\;and %R1,%2,%R0\";
1503 else if (GET_CODE (op2) == CONST_DOUBLE)
1505 int sign = CONST_DOUBLE_HIGH (op2);
1506 operands[2] = gen_rtx (CONST_INT, VOIDmode,
1507 CONST_DOUBLE_LOW (operands[1]));
1509 return \"mov %1,%0\;and %R1,%2,%R0\";
1510 return \"mov 0,%0\;and %R1,%2,%R0\";
1512 return \"and %1,%2,%0\;and %R1,%R2,%R0\";
1514 [(set_attr "length" "2")])
1516 (define_insn "andsi3"
1517 [(set (match_operand:SI 0 "register_operand" "=r")
1518 (and:SI (match_operand:SI 1 "arith_operand" "%r")
1519 (match_operand:SI 2 "arith_operand" "rI")))]
1524 [(set (match_operand:DI 0 "register_operand" "=r")
1525 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1526 (match_operand:DI 2 "register_operand" "r")))]
1528 "andn %2,%1,%0\;andn %R2,%R1,%R0"
1529 [(set_attr "length" "2")])
1532 [(set (match_operand:SI 0 "register_operand" "=r")
1533 (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1534 (match_operand:SI 2 "register_operand" "r")))]
1538 (define_expand "iordi3"
1539 [(set (match_operand:DI 0 "register_operand" "")
1540 (ior:DI (match_operand:DI 1 "arith_double_operand" "")
1541 (match_operand:DI 2 "arith_double_operand" "")))]
1546 [(set (match_operand:DI 0 "register_operand" "=r")
1547 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
1548 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1552 rtx op2 = operands[2];
1554 /* If constant is postive, upper bits zeroed, otherwise unchanged
1555 * give the assembler a chance to pick the move instruction. */
1556 if (GET_CODE (op2) == CONST_INT)
1558 int sign = INTVAL (op2);
1560 return \"mov -1,%0\;or %R1,%2,%R0\";
1561 return \"mov %1,%0\;or %R1,%2,%R0\";
1563 else if (GET_CODE (op2) == CONST_DOUBLE)
1565 int sign = CONST_DOUBLE_HIGH (op2);
1566 operands[2] = gen_rtx (CONST_INT, VOIDmode,
1567 CONST_DOUBLE_LOW (operands[1]));
1569 return \"mov -1,%0\;or %R1,%2,%R0\";
1570 return \"mov %1,%0\;or %R1,%2,%R0\";
1572 return \"or %1,%2,%0\;or %R1,%R2,%R0\";
1574 [(set_attr "length" "2")])
1576 (define_insn "iorsi3"
1577 [(set (match_operand:SI 0 "register_operand" "=r")
1578 (ior:SI (match_operand:SI 1 "arith_operand" "%r")
1579 (match_operand:SI 2 "arith_operand" "rI")))]
1584 [(set (match_operand:DI 0 "register_operand" "=r")
1585 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1586 (match_operand:DI 2 "register_operand" "r")))]
1588 "orn %2,%1,%0\;orn %R2,%R1,%R0"
1589 [(set_attr "length" "2")])
1592 [(set (match_operand:SI 0 "register_operand" "=r")
1593 (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1594 (match_operand:SI 2 "register_operand" "r")))]
1598 (define_expand "xordi3"
1599 [(set (match_operand:DI 0 "register_operand" "")
1600 (xor:DI (match_operand:DI 1 "arith_double_operand" "")
1601 (match_operand:DI 2 "arith_double_operand" "")))]
1606 [(set (match_operand:DI 0 "register_operand" "=r")
1607 (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
1608 (match_operand:DI 2 "arith_double_operand" "rHI")))]
1612 rtx op2 = operands[2];
1614 /* If constant is postive, upper bits zeroed, otherwise unchanged
1615 * give the assembler a chance to pick the move instruction. */
1616 if (GET_CODE (op2) == CONST_INT)
1618 int sign = INTVAL (op2);
1620 return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
1621 return \"mov %1,%0\;xor %R1,%2,%R0\";
1623 else if (GET_CODE (op2) == CONST_DOUBLE)
1625 int sign = CONST_DOUBLE_HIGH (op2);
1626 operands[2] = gen_rtx (CONST_INT, VOIDmode,
1627 CONST_DOUBLE_LOW (operands[1]));
1629 return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
1630 return \"mov %1,%0\;xor %R1,%2,%R0\";
1632 return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
1634 [(set_attr "length" "2")])
1636 (define_insn "xorsi3"
1637 [(set (match_operand:SI 0 "register_operand" "=r")
1638 (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
1639 (match_operand:SI 2 "arith_operand" "rI")))]
1643 ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
1644 ;; Combine now canonicalizes to the rightmost expression.
1646 [(set (match_operand:DI 0 "register_operand" "=r")
1647 (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
1648 (match_operand:DI 2 "register_operand" "r"))))]
1650 "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
1651 [(set_attr "length" "2")])
1654 [(set (match_operand:SI 0 "register_operand" "=r")
1655 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1656 (match_operand:SI 2 "arith_operand" "rI"))))]
1660 ;; These correspond to the above in the case where we also (or only)
1661 ;; want to set the condition code.
1666 (match_operator:SI 2 "cc_arithop"
1667 [(match_operand:SI 0 "arith_operand" "%r")
1668 (match_operand:SI 1 "arith_operand" "rI")])
1672 [(set_attr "type" "compare")])
1677 (match_operator:SI 3 "cc_arithop"
1678 [(match_operand:SI 1 "arith_operand" "%r")
1679 (match_operand:SI 2 "arith_operand" "rI")])
1681 (set (match_operand:SI 0 "register_operand" "=r")
1689 (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
1690 (match_operand:SI 1 "arith_operand" "rI")))
1693 "xnorcc %r0,%1,%%g0"
1694 [(set_attr "type" "compare")])
1699 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
1700 (match_operand:SI 2 "arith_operand" "rI")))
1702 (set (match_operand:SI 0 "register_operand" "=r")
1703 (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
1710 (match_operator:SI 2 "cc_arithopn"
1711 [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
1712 (match_operand:SI 1 "reg_or_0_operand" "rJ")])
1716 [(set_attr "type" "compare")])
1721 (match_operator:SI 3 "cc_arithopn"
1722 [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
1723 (match_operand:SI 2 "reg_or_0_operand" "rJ")])
1725 (set (match_operand:SI 0 "register_operand" "=r")
1730 ;; We cannot use the "neg" pseudo insn because the Sun assembler
1731 ;; does not know how to make it work for constants.
1733 (define_insn "negdi2"
1734 [(set (match_operand:DI 0 "register_operand" "=r")
1735 (neg:DI (match_operand:DI 1 "register_operand" "r")))
1736 (clobber (reg:SI 0))]
1738 "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
1739 [(set_attr "type" "unary")
1740 (set_attr "length" "2")])
1742 (define_insn "negsi2"
1743 [(set (match_operand:SI 0 "general_operand" "=r")
1744 (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
1747 [(set_attr "type" "unary")])
1750 [(set (reg:CC_NOOV 0)
1751 (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
1754 "subcc %%g0,%0,%%g0"
1755 [(set_attr "type" "compare")])
1758 [(set (reg:CC_NOOV 0)
1759 (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
1761 (set (match_operand:SI 0 "register_operand" "=r")
1762 (neg:SI (match_dup 1)))]
1765 [(set_attr "type" "unary")])
1767 ;; We cannot use the "not" pseudo insn because the Sun assembler
1768 ;; does not know how to make it work for constants.
1769 (define_expand "one_cmpldi2"
1770 [(set (match_operand:DI 0 "register_operand" "=r")
1771 (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
1776 [(set (match_operand:DI 0 "register_operand" "=r")
1777 (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
1781 rtx op1 = operands[1];
1783 if (GET_CODE (op1) == CONST_INT)
1785 int sign = INTVAL (op1);
1787 return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
1788 return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
1790 else if (GET_CODE (op1) == CONST_DOUBLE)
1792 int sign = CONST_DOUBLE_HIGH (op1);
1793 operands[1] = gen_rtx (CONST_INT, VOIDmode,
1794 CONST_DOUBLE_LOW (operands[1]));
1796 return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
1797 return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
1799 return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\";
1801 [(set_attr "type" "unary")
1802 (set_attr "length" "2")])
1804 (define_insn "one_cmplsi2"
1805 [(set (match_operand:SI 0 "register_operand" "=r")
1806 (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
1809 [(set_attr "type" "unary")])
1813 (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
1816 "xnorcc %%g0,%0,%%g0"
1817 [(set_attr "type" "compare")])
1821 (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
1823 (set (match_operand:SI 0 "register_operand" "=r")
1824 (not:SI (match_dup 1)))]
1827 [(set_attr "type" "unary")])
1829 ;; Floating point arithmetic instructions.
1831 (define_insn "adddf3"
1832 [(set (match_operand:DF 0 "register_operand" "=f")
1833 (plus:DF (match_operand:DF 1 "register_operand" "f")
1834 (match_operand:DF 2 "register_operand" "f")))]
1837 [(set_attr "type" "fp")])
1839 (define_insn "addsf3"
1840 [(set (match_operand:SF 0 "register_operand" "=f")
1841 (plus:SF (match_operand:SF 1 "register_operand" "f")
1842 (match_operand:SF 2 "register_operand" "f")))]
1845 [(set_attr "type" "fp")])
1847 (define_insn "subdf3"
1848 [(set (match_operand:DF 0 "register_operand" "=f")
1849 (minus:DF (match_operand:DF 1 "register_operand" "f")
1850 (match_operand:DF 2 "register_operand" "f")))]
1853 [(set_attr "type" "fp")])
1855 (define_insn "subsf3"
1856 [(set (match_operand:SF 0 "register_operand" "=f")
1857 (minus:SF (match_operand:SF 1 "register_operand" "f")
1858 (match_operand:SF 2 "register_operand" "f")))]
1861 [(set_attr "type" "fp")])
1863 (define_insn "muldf3"
1864 [(set (match_operand:DF 0 "register_operand" "=f")
1865 (mult:DF (match_operand:DF 1 "register_operand" "f")
1866 (match_operand:DF 2 "register_operand" "f")))]
1869 [(set_attr "type" "fpmul")])
1871 (define_insn "mulsf3"
1872 [(set (match_operand:SF 0 "register_operand" "=f")
1873 (mult:SF (match_operand:SF 1 "register_operand" "f")
1874 (match_operand:SF 2 "register_operand" "f")))]
1877 [(set_attr "type" "fpmul")])
1879 (define_insn "divdf3"
1880 [(set (match_operand:DF 0 "register_operand" "=f")
1881 (div:DF (match_operand:DF 1 "register_operand" "f")
1882 (match_operand:DF 2 "register_operand" "f")))]
1885 [(set_attr "type" "fpdiv")])
1887 (define_insn "divsf3"
1888 [(set (match_operand:SF 0 "register_operand" "=f")
1889 (div:SF (match_operand:SF 1 "register_operand" "f")
1890 (match_operand:SF 2 "register_operand" "f")))]
1893 [(set_attr "type" "fpdiv")])
1895 (define_insn "negdf2"
1896 [(set (match_operand:DF 0 "register_operand" "=f,f")
1897 (neg:DF (match_operand:DF 1 "register_operand" "0,f")))]
1901 fnegs %1,%0\;fmovs %R1,%R0"
1902 [(set_attr "type" "fp")
1903 (set_attr "length" "1,2")])
1906 (define_insn "negsf2"
1907 [(set (match_operand:SF 0 "register_operand" "=f")
1908 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
1911 [(set_attr "type" "fp")])
1913 (define_insn "absdf2"
1914 [(set (match_operand:DF 0 "register_operand" "=f,f")
1915 (abs:DF (match_operand:DF 1 "register_operand" "0,f")))]
1919 fabss %1,%0\;fmovs %R1,%R0"
1920 [(set_attr "type" "fp")
1921 (set_attr "length" "1,2")])
1923 (define_insn "abssf2"
1924 [(set (match_operand:SF 0 "register_operand" "=f")
1925 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
1928 [(set_attr "type" "fp")])
1930 (define_insn "sqrtdf2"
1931 [(set (match_operand:DF 0 "register_operand" "=f")
1932 (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
1935 [(set_attr "type" "fpsqrt")])
1937 (define_insn "sqrtsf2"
1938 [(set (match_operand:SF 0 "register_operand" "=f")
1939 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
1942 [(set_attr "type" "fpsqrt")])
1944 ;;- arithmetic shift instructions
1946 ;; We can trivially handle shifting the constant 1 by 64 bits.
1947 ;; For other shifts we use the library routine.
1948 ;; ??? Questionable, we can do better than this can't we?
1949 (define_expand "ashldi3"
1950 [(parallel [(set (match_operand:DI 0 "register_operand" "")
1951 (ashift:DI (match_operand:DI 1 "const_double_operand" "")
1952 (match_operand:SI 2 "register_operand" "")))
1953 (clobber (reg:SI 0))])]
1957 if (GET_CODE (operands[1]) == CONST_DOUBLE
1958 && CONST_DOUBLE_HIGH (operands[1]) == 0
1959 && CONST_DOUBLE_LOW (operands[1]) == 1)
1960 operands[1] = const1_rtx;
1961 else if (operands[1] != const1_rtx)
1965 ;; ??? Questionable, we can do better than this can't we?
1967 [(set (match_operand:DI 0 "register_operand" "=&r")
1968 (ashift:DI (const_int 1)
1969 (match_operand:SI 2 "register_operand" "r")))
1970 (clobber (reg:SI 0))]
1972 "subcc %2,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%2,%R0\;sll %0,%2,%0"
1973 [(set_attr "type" "multi")
1974 (set_attr "length" "5")])
1976 (define_insn "ashlsi3"
1977 [(set (match_operand:SI 0 "register_operand" "=r")
1978 (ashift:SI (match_operand:SI 1 "register_operand" "r")
1979 (match_operand:SI 2 "arith_operand" "rI")))]
1983 (define_insn "ashrsi3"
1984 [(set (match_operand:SI 0 "register_operand" "=r")
1985 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
1986 (match_operand:SI 2 "arith_operand" "rI")))]
1990 (define_insn "lshrsi3"
1991 [(set (match_operand:SI 0 "register_operand" "=r")
1992 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1993 (match_operand:SI 2 "arith_operand" "rI")))]
1997 ;; Unconditional and other jump instructions
1998 ;; Note that for the Sparc, by setting the annul bit on an unconditional
1999 ;; branch, the following insn is never executed. This saves us a nop,
2000 ;; but requires a debugger which can handle annuled branches.
2002 [(set (pc) (label_ref (match_operand 0 "" "")))]
2005 [(set_attr "type" "branch")])
2007 (define_expand "tablejump"
2008 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2009 (use (label_ref (match_operand 1 "" "")))])]
2013 /* We need to use the PC value in %o7 that was set up when the address
2014 of the label was loaded into a register, so we need different RTL. */
2017 emit_insn (gen_pic_tablejump (operands[0], operands[1]));
2022 (define_insn "pic_tablejump"
2023 [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2024 (use (label_ref (match_operand 1 "" "")))
2028 [(set_attr "type" "branch")])
2031 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2032 (use (label_ref (match_operand 1 "" "")))]
2035 [(set_attr "type" "branch")])
2038 [(set (pc) (label_ref (match_operand 0 "" "")))
2039 (set (reg:SI 15) (label_ref (match_dup 0)))]
2042 [(set_attr "type" "branch")])
2044 ;; This pattern recognizes the "instruction" that appears in
2045 ;; a function call that wants a structure value,
2046 ;; to inform the called function if compiled with Sun CC.
2048 ; [(match_operand:SI 0 "immediate_operand" "")]
2049 ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
2051 ; [(set_attr "type" "marker")])
2053 ;;- jump to subroutine
2054 (define_expand "call"
2055 ;; Note that this expression is not used for generating RTL.
2056 ;; All the RTL is generated explicitly below.
2057 [(call (match_operand:SI 0 "call_operand" "")
2058 (match_operand 3 "" "i"))]
2059 ;; operands[2] is next_arg_register
2060 ;; operands[3] is struct_value_size_rtx.
2064 rtx fn_rtx, nregs_rtx;
2066 if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
2068 /* This is really a PIC sequence. We want to represent
2069 it as a funny jump so it's delay slots can be filled.
2071 ??? But if this really *is* a CALL, will not it clobber the
2072 call-clobbered registers? We lose this if it is a JUMP_INSN.
2073 Why cannot we have delay slots filled if it were a CALL? */
2075 if (INTVAL (operands[3]) > 0)
2076 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2077 gen_rtx (SET, VOIDmode, pc_rtx,
2078 XEXP (operands[0], 0)),
2080 gen_rtx (CLOBBER, VOIDmode,
2081 gen_rtx (REG, SImode, 15)))));
2083 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2084 gen_rtx (SET, VOIDmode, pc_rtx,
2085 XEXP (operands[0], 0)),
2086 gen_rtx (CLOBBER, VOIDmode,
2087 gen_rtx (REG, SImode, 15)))));
2091 fn_rtx = operands[0];
2093 /* Count the number of parameter registers being used by this call.
2094 if that argument is NULL, it means we are using them all, which
2095 means 6 on the sparc. */
2098 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
2100 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2102 nregs_rtx = const0_rtx;
2105 if (INTVAL (operands[3]) > 0)
2106 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2107 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2109 gen_rtx (CLOBBER, VOIDmode,
2110 gen_rtx (REG, SImode, 15)))));
2112 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2113 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2114 gen_rtx (CLOBBER, VOIDmode,
2115 gen_rtx (REG, SImode, 15)))));
2119 /* If this call wants a structure value,
2120 emit an unimp insn to let the called function know about this. */
2121 if (INTVAL (operands[3]) > 0)
2123 rtx insn = emit_insn (operands[3]);
2124 SCHED_GROUP_P (insn) = 1;
2132 [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2133 (match_operand 1 "" ""))
2134 (clobber (reg:SI 15))]
2135 ;;- Do not use operand 1 for most machines.
2139 return \"call %a0,%1%#\";
2141 [(set_attr "type" "call")])
2143 ;; This is a call that wants a structure value.
2145 [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2146 (match_operand 1 "" ""))
2147 (match_operand 2 "immediate_operand" "")
2148 (clobber (reg:SI 15))]
2149 ;;- Do not use operand 1 for most machines.
2150 "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
2153 return \"call %a0,%1\;nop\;unimp %2\";
2155 [(set_attr "type" "call_no_delay_slot")])
2157 (define_expand "call_value"
2158 [(set (match_operand 0 "register_operand" "=rf")
2159 (call (match_operand:SI 1 "" "")
2160 (match_operand 4 "" "")))]
2161 ;; operand 3 is next_arg_register
2165 rtx fn_rtx, nregs_rtx;
2168 fn_rtx = operands[1];
2172 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
2174 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2176 nregs_rtx = const0_rtx;
2180 gen_rtx (SET, VOIDmode, operands[0],
2181 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2182 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15)));
2184 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2190 [(set (match_operand 0 "" "=rf")
2191 (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS"))
2192 (match_operand 2 "" "")))
2193 (clobber (reg:SI 15))]
2194 ;;- Do not use operand 2 for most machines.
2198 return \"call %a1,%2%#\";
2200 [(set_attr "type" "call")])
2202 (define_insn "return"
2205 "* return output_return (operands);"
2206 [(set_attr "type" "multi")])
2213 (define_insn "indirect_jump"
2214 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2217 [(set_attr "type" "branch")])
2219 (define_expand "nonlocal_goto"
2220 [(match_operand:SI 0 "general_operand" "")
2221 (match_operand:SI 1 "general_operand" "")
2222 (match_operand:SI 2 "general_operand" "")
2223 (match_operand:SI 3 "" "")]
2228 /* Trap instruction to flush all the registers window. */
2229 emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2230 gen_rtvec (1, const0_rtx), 0));
2231 /* Load the fp value for the containing fn into %fp.
2232 This is needed because operands[2] refers to %fp. */
2233 emit_move_insn (virtual_stack_vars_rtx, operands[0]);
2234 /* Find the containing function's current nonlocal goto handler,
2235 which will do any cleanups and then jump to the label. */
2236 emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]);
2237 /* Restore %fp from stack pointer value for containing function.
2238 The restore insn that follows will move this to %sp,
2239 and reload the appropriate value into %fp. */
2240 emit_move_insn (frame_pointer_rtx, operands[2]);
2241 /* Put in the static chain register the nonlocal label address. */
2242 emit_move_insn (static_chain_rtx, operands[3]);
2243 /* USE of frame_pointer_rtx added for consistency; not clear if
2245 emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
2246 emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
2247 emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
2248 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8)));
2249 /* Return, restoring reg window and jumping to goto handler. */
2250 emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode,
2251 gen_rtvec (1, const0_rtx), 1));
2255 ;; Special trap insn to flush register windows.
2257 [(unspec_volatile [(const_int 0)] 0)]
2262 [(unspec_volatile [(const_int 0)] 1)]
2264 "jmp %%o0+0\;restore")
2266 ;(define_insn "tail_call" ;; tail call
2267 ; [(set (pc) (match_operand 0 "memory_operand" "m"))]
2268 ; "tail_call_valid_p ()"
2269 ; "* return output_tail_call (operands, insn);"
2270 ; [(set_attr "type" "branch")])
2272 ;; Split up troublesome insns for better scheduling. */
2274 ;; The following patterns are straightforward. They can be applied
2275 ;; either before or after register allocation.
2278 [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")])
2279 (match_operand 2 "reg_or_0_operand" ""))
2280 (clobber (match_operand:SI 3 "register_operand" ""))]
2282 [(set (match_dup 3) (high:SI (match_dup 1)))
2283 (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))])
2288 [(set (match_operator 0 "memop"
2289 [(match_operand:SI 1 "immediate_operand" "")])
2290 (match_operand 2 "general_operand" ""))
2291 (clobber (match_operand:SI 3 "register_operand" ""))]
2293 [(set (match_op_dup 0 [(match_dup 1)])
2297 operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]),
2302 [(set (match_operand 0 "register_operand" "")
2303 (match_operator 1 "memop"
2304 [(match_operand:SI 2 "immediate_operand" "")]))]
2307 (match_op_dup 1 [(match_dup 2)]))]
2310 operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]),
2314 ;; Sign- and Zero-extend operations can have symbolic memory operands.
2317 [(set (match_operand 0 "register_operand" "")
2318 (match_operator 1 "extend_op"
2319 [(match_operator 2 "memop"
2320 [(match_operand:SI 3 "immediate_operand" "")])]))]
2323 (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))]
2326 operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]),
2331 [(set (match_operand:SI 0 "register_operand" "")
2332 (match_operand:SI 1 "immediate_operand" ""))]
2333 "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2334 || GET_CODE (operands[1]) == CONST
2335 || GET_CODE (operands[1]) == LABEL_REF)"
2336 [(set (match_dup 0) (high:SI (match_dup 1)))
2338 (lo_sum:SI (match_dup 0) (match_dup 1)))]
2341 ;; LABEL_REFs are not modified by `legitimize_pic_address`
2342 ;; so do not recurse infinitely in the PIC case.
2344 [(set (match_operand:SI 0 "register_operand" "")
2345 (match_operand:SI 1 "immediate_operand" ""))]
2346 "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
2347 || GET_CODE (operands[1]) == CONST)"
2348 [(set (match_dup 0) (match_dup 1))]
2351 operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0);
2354 ;; These split sne/seq insns. The forms of the resulting insns are
2355 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
2356 ;; Nothing will look at these in detail after splitting has occurred.
2359 [(set (match_operand:SI 0 "register_operand" "")
2360 (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2361 (clobber (reg:CC 0))]
2363 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2365 (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
2369 [(set (match_operand:SI 0 "register_operand" "")
2370 (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2372 (clobber (reg:CC 0))]
2374 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2376 (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
2380 [(set (match_operand:SI 0 "register_operand" "")
2381 (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
2382 (clobber (reg:CC 0))]
2384 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2386 (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
2390 [(set (match_operand:SI 0 "register_operand" "")
2391 (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2393 (clobber (reg:CC 0))]
2395 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2397 (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
2401 [(set (match_operand:SI 0 "register_operand" "")
2402 (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
2404 (match_operand:SI 2 "register_operand" "")))
2405 (clobber (reg:CC 0))]
2407 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2409 (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
2414 [(set (match_operand:SI 0 "register_operand" "")
2415 (minus:SI (match_operand:SI 2 "register_operand" "")
2416 (ne:SI (match_operand:SI 1 "register_operand" "")
2418 (clobber (reg:CC 0))]
2420 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2422 (set (match_dup 0) (minus:SI (match_dup 2)
2423 (ltu:SI (reg:CC 0) (const_int 0))))]
2427 [(set (match_operand:SI 0 "register_operand" "")
2428 (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
2430 (match_operand:SI 2 "register_operand" "")))
2431 (clobber (reg:CC 0))]
2433 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2435 (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
2440 [(set (match_operand:SI 0 "register_operand" "")
2441 (minus:SI (match_operand:SI 2 "register_operand" "")
2442 (eq:SI (match_operand:SI 1 "register_operand" "")
2444 (clobber (reg:CC 0))]
2446 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
2448 (set (match_dup 0) (minus:SI (match_dup 2)
2449 (geu:SI (reg:CC 0) (const_int 0))))]
2452 ;; Peepholes go at the end.
2454 ;; Optimize the case of following a reg-reg move with a test
2455 ;; of reg just moved.
2458 [(set (match_operand:SI 0 "register_operand" "=r")
2459 (match_operand:SI 1 "register_operand" "r"))
2461 (compare:CC (match_operand:SI 2 "register_operand" "r")
2463 "rtx_equal_p (operands[2], operands[0])
2464 || rtx_equal_p (operands[2], operands[1])"
2466 [(set_attr "type" "move")])
2468 ;; Do {sign,zero}-extended compares somewhat more efficiently.
2469 ;; ??? Is this now the Right Way to do this? Or will SCRATCH
2470 ;; eventually have some impact here?
2473 [(set (match_operand:HI 0 "register_operand" "")
2474 (match_operand:HI 1 "memory_operand" ""))
2475 (set (match_operand:SI 2 "register_operand" "")
2476 (sign_extend:SI (match_dup 0)))
2478 (compare:CC (match_dup 2)
2481 "ldsh %1,%0\;orcc %0,%%g0,%2")
2484 [(set (match_operand:QI 0 "register_operand" "")
2485 (match_operand:QI 1 "memory_operand" ""))
2486 (set (match_operand:SI 2 "register_operand" "")
2487 (sign_extend:SI (match_dup 0)))
2489 (compare:CC (match_dup 2)
2492 "ldsb %1,%0\;orcc %0,%%g0,%2")
2495 [(set (match_operand:HI 0 "register_operand" "")
2496 (match_operand:HI 1 "memory_operand" ""))
2497 (set (match_operand:SI 2 "register_operand" "")
2498 (sign_extend:SI (match_dup 0)))]
2499 "dead_or_set_p (insn, operands[0])"
2502 warning (\"bad peephole\");
2503 if (! MEM_VOLATILE_P (operands[1]))
2505 return \"ldsh %1,%2\";
2509 [(set (match_operand:QI 0 "register_operand" "")
2510 (match_operand:QI 1 "memory_operand" ""))
2511 (set (match_operand:SI 2 "register_operand" "")
2512 (sign_extend:SI (match_dup 0)))]
2513 "dead_or_set_p (insn, operands[0])"
2516 warning (\"bad peephole\");
2517 if (! MEM_VOLATILE_P (operands[1]))
2519 return \"ldsb %1,%2\";
2522 ;; Floating-point move peepholes
2525 [(set (match_operand:SI 0 "register_operand" "=r")
2526 (lo_sum:SI (match_dup 0)
2527 (match_operand:SI 1 "immediate_operand" "i")))
2528 (set (match_operand:DF 2 "register_operand" "=fr")
2529 (mem:DF (match_dup 0)))]
2530 "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
2533 /* Go by way of output_move_double in case the register in operand 2
2534 is not properly aligned for ldd. */
2535 operands[1] = gen_rtx (MEM, DFmode,
2536 gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
2537 operands[0] = operands[2];
2538 return output_move_double (operands);
2542 [(set (match_operand:SI 0 "register_operand" "=r")
2543 (lo_sum:SI (match_dup 0)
2544 (match_operand:SI 1 "immediate_operand" "i")))
2545 (set (match_operand:SF 2 "register_operand" "=fr")
2546 (mem:SF (match_dup 0)))]
2547 "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
2548 "ld [%0+%%lo(%a1)],%2")
2550 ;; Return peepholes. First the "normal" ones
2553 [(set (match_operand:SI 0 "restore_operand" "")
2554 (match_operand:SI 1 "arith_operand" "rI"))
2559 if (current_function_returns_struct)
2560 return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
2562 return \"ret\;restore %%g0,%1,%Y0\";
2564 [(set_attr "type" "multi")])
2567 [(set (match_operand:SI 0 "restore_operand" "")
2568 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
2569 (match_operand:SI 2 "arith_operand" "rI")))
2574 if (current_function_returns_struct)
2575 return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
2577 return \"ret\;restore %r1,%2,%Y0\";
2579 [(set_attr "type" "multi")])
2581 ;; Turned off because it should never match (subtracting a constant
2582 ;; is turned into addition) and because it would do the wrong thing
2583 ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
2585 ;; [(set (match_operand:SI 0 "restore_operand" "")
2586 ;; (minus:SI (match_operand:SI 1 "register_operand" "r")
2587 ;; (match_operand:SI 2 "small_int" "I")))
2589 ;; "! TARGET_EPILOGUE"
2590 ;; "ret\;restore %1,-(%2),%Y0"
2591 ;; [(set_attr "type" "multi")])
2593 ;; The following pattern is only generated by delayed-branch scheduling,
2594 ;; when the insn winds up in the epilogue.
2597 (match_operand:SF 0 "register_operand" "f"))
2600 "ret\;fmovs %0,%%f0")
2602 ;; Now peepholes to go a call followed by a jump.
2605 [(parallel [(set (match_operand 0 "" "")
2606 (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r"))
2607 (match_operand 2 "" "")))
2608 (clobber (reg:SI 15))])
2609 (set (pc) (label_ref (match_operand 3 "" "")))]
2610 "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
2613 return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
2617 [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2618 (match_operand 1 "" ""))
2619 (clobber (reg:SI 15))])
2620 (set (pc) (label_ref (match_operand 2 "" "")))]
2621 "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
2624 return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
2628 [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
2629 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
2631 (clobber (reg:CC 0))])
2632 (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]
2635 [(set_attr "type" "compare")])
2637 ;;- Local variables:
2639 ;;- comment-start: ";;- "
2640 ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
2641 ;;- eval: (modify-syntax-entry ?[ "(]")
2642 ;;- eval: (modify-syntax-entry ?] ")[")
2643 ;;- eval: (modify-syntax-entry ?{ "(}")
2644 ;;- eval: (modify-syntax-entry ?} "){")