1 ;;- Machine description for SPARC chip for GNU C compiler
2 ;; Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
3 ;; Contributed by Michael Tiemann (tiemann@cygnus.com)
4 ;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25 ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
26 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
27 ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
28 ;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
29 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
31 ;; Architecture type. Arch32bit includes v7, sparclite, v8.
33 (define_attr "arch" "arch32bit,arch64bit"
34 (const (symbol_ref "sparc_arch_type")))
36 ;; CPU type. This is only used for instruction scheduling
37 (define_attr "cpu" "cypress,supersparc"
39 (cond [(symbol_ref "TARGET_SUPERSPARC") (const_string "supersparc")]
40 (const_string "cypress"))))
42 ;; Insn type. Used to default other attribute values.
44 ;; type "unary" insns have one input operand (1) and one output operand (0)
45 ;; type "binary" insns have two input operands (1,2) and one output (0)
46 ;; type "compare" insns have one or two input operands (0,1) and no output
47 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
50 "move,unary,binary,compare,load,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc"
51 (const_string "binary"))
53 ;; Set true if insn uses call-clobbered intermediate register.
54 (define_attr "use_clobbered" "false,true"
55 (if_then_else (and (eq_attr "type" "address")
56 (match_operand 0 "clobbered_register" ""))
58 (const_string "false")))
60 ;; Length (in # of insns).
61 (define_attr "length" ""
62 (cond [(eq_attr "type" "load,fpload")
63 (if_then_else (match_operand 1 "symbolic_memory_operand" "")
64 (const_int 2) (const_int 1))
66 (eq_attr "type" "store,fpstore")
67 (if_then_else (match_operand 0 "symbolic_memory_operand" "")
68 (const_int 2) (const_int 1))
70 (eq_attr "type" "address") (const_int 2)
72 (eq_attr "type" "binary")
73 (if_then_else (ior (match_operand 2 "arith_operand" "")
74 (match_operand 2 "arith_double_operand" ""))
75 (const_int 1) (const_int 3))
77 (eq_attr "type" "multi") (const_int 2)
79 (eq_attr "type" "move,unary")
80 (if_then_else (ior (match_operand 1 "arith_operand" "")
81 (match_operand 1 "arith_double_operand" ""))
82 (const_int 1) (const_int 2))]
86 (define_asm_attributes
87 [(set_attr "length" "1")
88 (set_attr "type" "multi")])
90 ;; Attributes for instruction and branch scheduling
92 (define_attr "in_call_delay" "false,true"
93 (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
94 (const_string "false")
95 (eq_attr "type" "load,fpload,store,fpstore")
96 (if_then_else (eq_attr "length" "1")
98 (const_string "false"))
99 (eq_attr "type" "address")
100 (if_then_else (eq_attr "use_clobbered" "false")
101 (const_string "true")
102 (const_string "false"))]
103 (if_then_else (eq_attr "length" "1")
104 (const_string "true")
105 (const_string "false"))))
107 (define_delay (eq_attr "type" "call")
108 [(eq_attr "in_call_delay" "true") (nil) (nil)])
110 ;; ??? Should implement the notion of predelay slots for floating point
111 ;; branches. This would allow us to remove the nop always inserted before
112 ;; a floating point branch.
114 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
115 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
116 ;; This is because doing so will add several pipeline stalls to the path
117 ;; that the load/store did not come from. Unfortunately, there is no way
118 ;; to prevent fill_eager_delay_slots from using load/store without completely
119 ;; disabling them. For the SPEC benchmark set, this is a serious lose,
120 ;; because it prevents us from moving back the final store of inner loops.
122 (define_attr "in_branch_delay" "false,true"
123 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
124 (eq_attr "length" "1"))
125 (const_string "true")
126 (const_string "false")))
128 (define_attr "in_uncond_branch_delay" "false,true"
129 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
130 (eq_attr "length" "1"))
131 (const_string "true")
132 (const_string "false")))
134 (define_attr "in_annul_branch_delay" "false,true"
135 (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
136 (eq_attr "length" "1"))
137 (const_string "true")
138 (const_string "false")))
140 (define_delay (eq_attr "type" "branch")
141 [(eq_attr "in_branch_delay" "true")
142 (nil) (eq_attr "in_annul_branch_delay" "true")])
144 (define_delay (eq_attr "type" "uncond_branch")
145 [(eq_attr "in_uncond_branch_delay" "true")
148 ;; Function units of the SPARC
150 ;; (define_function_unit {name} {num-units} {n-users} {test}
151 ;; {ready-delay} {issue-delay} [{conflict-list}])
154 ;; (Noted only for documentation; units that take one cycle do not need to
157 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
160 ;; (define_function_unit "alu" 1 0
161 ;; (eq_attr "type" "unary,binary,move,address") 1 0)
163 ;; ---- cypress CY7C602 scheduling:
164 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
165 (define_function_unit "memory" 1 0
166 (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "cypress")) 2 2)
168 ;; SPARC has two floating-point units: the FP ALU,
169 ;; and the FP MUL/DIV/SQRT unit.
170 ;; Instruction timings on the CY7C602 are as follows
184 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
185 ;; More insns cause the chip to stall.
187 (define_function_unit "fp_alu" 1 0
188 (and (eq_attr "type" "fp") (eq_attr "cpu" "cypress")) 5 5)
189 (define_function_unit "fp_mds" 1 0
190 (and (eq_attr "type" "fpmul") (eq_attr "cpu" "cypress")) 7 7)
191 (define_function_unit "fp_mds" 1 0
192 (and (eq_attr "type" "fpdivs,fpdivd") (eq_attr "cpu" "cypress")) 37 37)
193 (define_function_unit "fp_mds" 1 0
194 (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "cypress")) 63 63)
196 ;; ----- The TMS390Z55 scheduling
197 ;; The Supersparc can issue 1 - 3 insns per cycle; here we assume
198 ;; three insns/cycle, and hence multiply all costs by three.
199 ;; Combinations up to two integer, one ld/st, one fp.
200 ;; Memory delivers its result in one cycle to IU, zero cycles to FP
201 (define_function_unit "memory" 1 0
202 (and (eq_attr "type" "load") (eq_attr "cpu" "supersparc")) 3 3)
203 (define_function_unit "memory" 1 0
204 (and (eq_attr "type" "fpload") (eq_attr "cpu" "supersparc")) 1 3)
205 ;; at least one in three instructions can be a mem opt.
206 (define_function_unit "memory" 1 0
207 (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "supersparc")) 1 3)
208 ;; at least one in three instructions can be a shift op.
209 (define_function_unit "shift" 1 0
210 (and (eq_attr "type" "shift") (eq_attr "cpu" "supersparc")) 1 3)
212 ;; There are only two write ports to the integer register file
213 ;; A store also uses a write port
214 (define_function_unit "iwport" 2 0
215 (and (eq_attr "type" "load,store,shift,ialu") (eq_attr "cpu" "supersparc")) 1 3)
217 ;; Timings; throughput/latency
218 ;; FADD 1/3 add/sub, format conv, compar, abs, neg
226 (define_function_unit "fp_alu" 1 0
227 (and (eq_attr "type" "fp,fpcmp") (eq_attr "cpu" "supersparc")) 9 3)
228 (define_function_unit "fp_mds" 1 0
229 (and (eq_attr "type" "fpmul") (eq_attr "cpu" "supersparc")) 9 3)
230 (define_function_unit "fp_mds" 1 0
231 (and (eq_attr "type" "fpdivs") (eq_attr "cpu" "supersparc")) 18 12)
232 (define_function_unit "fp_mds" 1 0
233 (and (eq_attr "type" "fpdivd") (eq_attr "cpu" "supersparc")) 27 21)
234 (define_function_unit "fp_mds" 1 0
235 (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "supersparc")) 36 30)
236 (define_function_unit "fp_mds" 1 0
237 (and (eq_attr "type" "imul") (eq_attr "cpu" "supersparc")) 12 12)
239 ;; Compare instructions.
240 ;; This controls RTL generation and register allocation.
242 ;; We generate RTL for comparisons and branches by having the cmpxx
243 ;; patterns store away the operands. Then, the scc and bcc patterns
244 ;; emit RTL for both the compare and the branch.
246 ;; We do this because we want to generate different code for an sne and
247 ;; seq insn. In those cases, if the second operand of the compare is not
248 ;; const0_rtx, we want to compute the xor of the two operands and test
251 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
252 ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
253 ;; insns that actually require more than one machine instruction.
255 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
257 (define_expand "cmpsi"
259 (compare:CC (match_operand:SI 0 "register_operand" "")
260 (match_operand:SI 1 "arith_operand" "")))]
264 sparc_compare_op0 = operands[0];
265 sparc_compare_op1 = operands[1];
269 (define_expand "cmpdi"
271 (compare:CCX (match_operand:DI 0 "register_operand" "")
272 (match_operand:DI 1 "arith_double_operand" "")))]
276 sparc_compare_op0 = operands[0];
277 sparc_compare_op1 = operands[1];
281 (define_expand "cmpsf"
283 (compare:CCFP (match_operand:SF 0 "register_operand" "")
284 (match_operand:SF 1 "register_operand" "")))]
288 sparc_compare_op0 = operands[0];
289 sparc_compare_op1 = operands[1];
293 (define_expand "cmpdf"
295 (compare:CCFP (match_operand:DF 0 "register_operand" "")
296 (match_operand:DF 1 "register_operand" "")))]
300 sparc_compare_op0 = operands[0];
301 sparc_compare_op1 = operands[1];
305 (define_expand "cmptf"
307 (compare:CCFP (match_operand:TF 0 "register_operand" "")
308 (match_operand:TF 1 "register_operand" "")))]
312 sparc_compare_op0 = operands[0];
313 sparc_compare_op1 = operands[1];
317 ;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this
318 ;; without jumps using the addx/subx instructions. For seq/sne on v9 we use
319 ;; the same code as v8 (the addx/subx method has more applications). The
320 ;; exception to this is "reg != 0" which can be done in one instruction on v9
321 ;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do
324 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
325 ;; generate addcc/subcc instructions.
327 (define_expand "seqsi_special"
329 (xor:SI (match_operand:SI 1 "register_operand" "")
330 (match_operand:SI 2 "register_operand" "")))
331 (parallel [(set (match_operand:SI 0 "register_operand" "")
332 (eq:SI (match_dup 3) (const_int 0)))
333 (clobber (reg:CC 0))])]
335 "{ operands[3] = gen_reg_rtx (SImode); }")
337 (define_expand "seqdi_special"
339 (xor:DI (match_operand:DI 1 "register_operand" "")
340 (match_operand:DI 2 "register_operand" "")))
341 (parallel [(set (match_operand:DI 0 "register_operand" "")
342 (eq:DI (match_dup 3) (const_int 0)))
343 (clobber (reg:CCX 0))])]
345 "{ operands[3] = gen_reg_rtx (DImode); }")
347 (define_expand "snesi_special"
349 (xor:SI (match_operand:SI 1 "register_operand" "")
350 (match_operand:SI 2 "register_operand" "")))
351 (parallel [(set (match_operand:SI 0 "register_operand" "")
352 (ne:SI (match_dup 3) (const_int 0)))
353 (clobber (reg:CC 0))])]
355 "{ operands[3] = gen_reg_rtx (SImode); }")
357 (define_expand "snedi_special"
359 (xor:DI (match_operand:DI 1 "register_operand" "")
360 (match_operand:DI 2 "register_operand" "")))
361 (parallel [(set (match_operand:DI 0 "register_operand" "")
362 (ne:DI (match_dup 3) (const_int 0)))
363 (clobber (reg:CCX 0))])]
365 "{ operands[3] = gen_reg_rtx (DImode); }")
367 (define_expand "seqdi_special_trunc"
369 (xor:DI (match_operand:DI 1 "register_operand" "")
370 (match_operand:DI 2 "register_operand" "")))
371 (parallel [(set (match_operand:SI 0 "register_operand" "")
372 (eq:SI (subreg:SI (match_dup 3) 0) (const_int 0)))
373 (clobber (reg:CC 0))])]
375 "{ operands[3] = gen_reg_rtx (DImode); }")
377 (define_expand "snedi_special_trunc"
379 (xor:DI (match_operand:DI 1 "register_operand" "")
380 (match_operand:DI 2 "register_operand" "")))
381 (parallel [(set (match_operand:SI 0 "register_operand" "")
382 (ne:SI (subreg:SI (match_dup 3) 0) (const_int 0)))
383 (clobber (reg:CC 0))])]
385 "{ operands[3] = gen_reg_rtx (DImode); }")
387 (define_expand "seqsi_special_extend"
388 [(set (subreg:SI (match_dup 3) 0)
389 (xor:SI (match_operand:SI 1 "register_operand" "")
390 (match_operand:SI 2 "register_operand" "")))
391 (parallel [(set (match_operand:DI 0 "register_operand" "")
392 (eq:DI (match_dup 3) (const_int 0)))
393 (clobber (reg:CCX 0))])]
395 "{ operands[3] = gen_reg_rtx (DImode); }")
397 (define_expand "snesi_special_extend"
398 [(set (subreg:SI (match_dup 3) 0)
399 (xor:SI (match_operand:SI 1 "register_operand" "")
400 (match_operand:SI 2 "register_operand" "")))
401 (parallel [(set (match_operand:DI 0 "register_operand" "")
402 (ne:DI (match_dup 3) (const_int 0)))
403 (clobber (reg:CCX 0))])]
405 "{ operands[3] = gen_reg_rtx (DImode); }")
407 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
408 ;; However, the code handles both SImode and DImode.
410 [(set (match_operand:SI 0 "intreg_operand" "")
411 (eq:SI (match_dup 1) (const_int 0)))]
415 if (GET_MODE (sparc_compare_op0) == SImode)
419 if (GET_MODE (operands[0]) == SImode)
420 pat = gen_seqsi_special (operands[0], sparc_compare_op0,
422 else if (! TARGET_V9)
425 pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
430 else if (GET_MODE (sparc_compare_op0) == DImode)
434 if (GET_MODE (operands[0]) == SImode)
435 pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
437 else if (! TARGET_V9)
440 pat = gen_seqdi_special (operands[0], sparc_compare_op0,
445 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
447 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
448 emit_insn (gen_sne (operands[0]));
453 if (gen_v9_scc (EQ, operands))
457 operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
460 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
461 ;; However, the code handles both SImode and DImode.
463 [(set (match_operand:SI 0 "intreg_operand" "")
464 (ne:SI (match_dup 1) (const_int 0)))]
468 if (GET_MODE (sparc_compare_op0) == SImode)
472 if (GET_MODE (operands[0]) == SImode)
473 pat = gen_snesi_special (operands[0], sparc_compare_op0,
475 else if (! TARGET_V9)
478 pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
483 else if (GET_MODE (sparc_compare_op0) == DImode)
487 if (GET_MODE (operands[0]) == SImode)
488 pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
490 else if (! TARGET_V9)
493 pat = gen_snedi_special (operands[0], sparc_compare_op0,
498 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
500 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
501 emit_insn (gen_sne (operands[0]));
506 if (gen_v9_scc (NE, operands))
510 operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
514 [(set (match_operand:SI 0 "intreg_operand" "")
515 (gt:SI (match_dup 1) (const_int 0)))]
519 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
521 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
522 emit_insn (gen_sne (operands[0]));
527 if (gen_v9_scc (GT, operands))
531 operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
535 [(set (match_operand:SI 0 "intreg_operand" "")
536 (lt:SI (match_dup 1) (const_int 0)))]
540 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
542 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
543 emit_insn (gen_sne (operands[0]));
548 if (gen_v9_scc (LT, operands))
552 operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
556 [(set (match_operand:SI 0 "intreg_operand" "")
557 (ge:SI (match_dup 1) (const_int 0)))]
561 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
563 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
564 emit_insn (gen_sne (operands[0]));
569 if (gen_v9_scc (GE, operands))
573 operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
577 [(set (match_operand:SI 0 "intreg_operand" "")
578 (le:SI (match_dup 1) (const_int 0)))]
582 if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
584 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
585 emit_insn (gen_sne (operands[0]));
590 if (gen_v9_scc (LE, operands))
594 operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
597 (define_expand "sgtu"
598 [(set (match_operand:SI 0 "intreg_operand" "")
599 (gtu:SI (match_dup 1) (const_int 0)))]
607 /* We can do ltu easily, so if both operands are registers, swap them and
609 if ((GET_CODE (sparc_compare_op0) == REG
610 || GET_CODE (sparc_compare_op0) == SUBREG)
611 && (GET_CODE (sparc_compare_op1) == REG
612 || GET_CODE (sparc_compare_op1) == SUBREG))
614 tem = sparc_compare_op0;
615 sparc_compare_op0 = sparc_compare_op1;
616 sparc_compare_op1 = tem;
617 emit_insn (gen_sltu (operands[0]));
623 if (gen_v9_scc (GTU, operands))
626 operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
629 (define_expand "sltu"
630 [(set (match_operand:SI 0 "intreg_operand" "")
631 (ltu:SI (match_dup 1) (const_int 0)))]
637 if (gen_v9_scc (LTU, operands))
640 operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
643 (define_expand "sgeu"
644 [(set (match_operand:SI 0 "intreg_operand" "")
645 (geu:SI (match_dup 1) (const_int 0)))]
651 if (gen_v9_scc (GEU, operands))
654 operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
657 (define_expand "sleu"
658 [(set (match_operand:SI 0 "intreg_operand" "")
659 (leu:SI (match_dup 1) (const_int 0)))]
667 /* We can do geu easily, so if both operands are registers, swap them and
669 if ((GET_CODE (sparc_compare_op0) == REG
670 || GET_CODE (sparc_compare_op0) == SUBREG)
671 && (GET_CODE (sparc_compare_op1) == REG
672 || GET_CODE (sparc_compare_op1) == SUBREG))
674 tem = sparc_compare_op0;
675 sparc_compare_op0 = sparc_compare_op1;
676 sparc_compare_op1 = tem;
677 emit_insn (gen_sgeu (operands[0]));
683 if (gen_v9_scc (LEU, operands))
686 operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
689 ;; Now the DEFINE_INSNs for the compare and scc cases. First the compares.
691 (define_insn "*cmpsi_insn"
693 (compare:CC (match_operand:SI 0 "register_operand" "r")
694 (match_operand:SI 1 "arith_operand" "rI")))]
697 [(set_attr "type" "compare")])
699 (define_insn "*cmpsf_fpe_sp32"
701 (compare:CCFPE (match_operand:SF 0 "register_operand" "f")
702 (match_operand:SF 1 "register_operand" "f")))]
703 "! TARGET_V9 && TARGET_FPU"
705 [(set_attr "type" "fpcmp")])
707 (define_insn "*cmpdf_fpe_sp32"
709 (compare:CCFPE (match_operand:DF 0 "register_operand" "e")
710 (match_operand:DF 1 "register_operand" "e")))]
711 "! TARGET_V9 && TARGET_FPU"
713 [(set_attr "type" "fpcmp")])
715 (define_insn "*cmptf_fpe_sp32"
717 (compare:CCFPE (match_operand:TF 0 "register_operand" "e")
718 (match_operand:TF 1 "register_operand" "e")))]
719 "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
721 [(set_attr "type" "fpcmp")])
723 (define_insn "*cmpsf_fp_sp32"
725 (compare:CCFP (match_operand:SF 0 "register_operand" "f")
726 (match_operand:SF 1 "register_operand" "f")))]
727 "! TARGET_V9 && TARGET_FPU"
729 [(set_attr "type" "fpcmp")])
731 (define_insn "*cmpdf_fp_sp32"
733 (compare:CCFP (match_operand:DF 0 "register_operand" "e")
734 (match_operand:DF 1 "register_operand" "e")))]
735 "! TARGET_V9 && TARGET_FPU"
737 [(set_attr "type" "fpcmp")])
739 (define_insn "*cmptf_fp_sp32"
741 (compare:CCFP (match_operand:TF 0 "register_operand" "e")
742 (match_operand:TF 1 "register_operand" "e")))]
743 "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
745 [(set_attr "type" "fpcmp")])
747 (define_insn "*cmpdi_sp64"
749 (compare:CCX (match_operand:DI 0 "register_operand" "r")
750 (match_operand:DI 1 "arith_double_operand" "rHI")))]
753 [(set_attr "type" "compare")])
755 (define_insn "*cmpsf_fpe_sp64"
756 [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
757 (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
758 (match_operand:SF 2 "register_operand" "f")))]
759 "TARGET_V9 && TARGET_FPU"
761 [(set_attr "type" "fpcmp")])
763 (define_insn "*cmpdf_fpe_sp64"
764 [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
765 (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
766 (match_operand:DF 2 "register_operand" "e")))]
767 "TARGET_V9 && TARGET_FPU"
769 [(set_attr "type" "fpcmp")])
771 (define_insn "*cmptf_fpe_sp64"
772 [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
773 (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
774 (match_operand:TF 2 "register_operand" "e")))]
775 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
777 [(set_attr "type" "fpcmp")])
779 (define_insn "*cmpsf_fp_sp64"
780 [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
781 (compare:CCFP (match_operand:SF 1 "register_operand" "f")
782 (match_operand:SF 2 "register_operand" "f")))]
783 "TARGET_V9 && TARGET_FPU"
785 [(set_attr "type" "fpcmp")])
787 (define_insn "*cmpdf_fp_sp64"
788 [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
789 (compare:CCFP (match_operand:DF 1 "register_operand" "e")
790 (match_operand:DF 2 "register_operand" "e")))]
791 "TARGET_V9 && TARGET_FPU"
793 [(set_attr "type" "fpcmp")])
795 (define_insn "*cmptf_fp_sp64"
796 [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
797 (compare:CCFP (match_operand:TF 1 "register_operand" "e")
798 (match_operand:TF 2 "register_operand" "e")))]
799 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
801 [(set_attr "type" "fpcmp")])
803 ;; The SEQ and SNE patterns are special because they can be done
804 ;; without any branching and do not involve a COMPARE.
806 (define_insn "*snesi_zero"
807 [(set (match_operand:SI 0 "register_operand" "=r")
808 (ne:SI (match_operand:SI 1 "register_operand" "r")
810 (clobber (reg:CC 0))]
812 "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
813 [(set_attr "type" "unary")
814 (set_attr "length" "2")])
816 (define_insn "*neg_snesi_zero"
817 [(set (match_operand:SI 0 "register_operand" "=r")
818 (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
820 (clobber (reg:CC 0))]
822 "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
823 [(set_attr "type" "unary")
824 (set_attr "length" "2")])
826 (define_insn "*snedi_zero"
827 [(set (match_operand:DI 0 "register_operand" "=r")
828 (ne:DI (match_operand:DI 1 "register_operand" "r")
830 (clobber (reg:CCX 0))]
832 "mov 0,%0\;movrnz %1,1,%0"
833 [(set_attr "type" "unary")
834 (set_attr "length" "2")])
836 (define_insn "*neg_snedi_zero"
837 [(set (match_operand:DI 0 "register_operand" "=r")
838 (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
840 (clobber (reg:CCX 0))]
842 "mov 0,%0\;movrnz %1,-1,%0"
843 [(set_attr "type" "unary")
844 (set_attr "length" "2")])
846 (define_insn "*seqsi_zero"
847 [(set (match_operand:SI 0 "register_operand" "=r")
848 (eq:SI (match_operand:SI 1 "register_operand" "r")
850 (clobber (reg:CC 0))]
852 "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
853 [(set_attr "type" "unary")
854 (set_attr "length" "2")])
856 (define_insn "*neg_seqsi_zero"
857 [(set (match_operand:SI 0 "register_operand" "=r")
858 (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
860 (clobber (reg:CC 0))]
862 "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
863 [(set_attr "type" "unary")
864 (set_attr "length" "2")])
866 (define_insn "*seqdi_zero"
867 [(set (match_operand:DI 0 "register_operand" "=r")
868 (eq:DI (match_operand:DI 1 "register_operand" "r")
870 (clobber (reg:CCX 0))]
872 "mov 0,%0\;movrz %1,1,%0"
873 [(set_attr "type" "unary")
874 (set_attr "length" "2")])
876 (define_insn "*neg_seqdi_zero"
877 [(set (match_operand:DI 0 "register_operand" "=r")
878 (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
880 (clobber (reg:CCX 0))]
882 "mov 0,%0\;movrz %1,-1,%0"
883 [(set_attr "type" "unary")
884 (set_attr "length" "2")])
886 ;; We can also do (x + (i == 0)) and related, so put them in.
887 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
890 (define_insn "*x_plus_i_ne_0"
891 [(set (match_operand:SI 0 "register_operand" "=r")
892 (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
894 (match_operand:SI 2 "register_operand" "r")))
895 (clobber (reg:CC 0))]
897 "subcc %%g0,%1,%%g0\;addx %2,0,%0"
898 [(set_attr "length" "2")])
900 (define_insn "*x_minus_i_ne_0"
901 [(set (match_operand:SI 0 "register_operand" "=r")
902 (minus:SI (match_operand:SI 2 "register_operand" "r")
903 (ne:SI (match_operand:SI 1 "register_operand" "r")
905 (clobber (reg:CC 0))]
907 "subcc %%g0,%1,%%g0\;subx %2,0,%0"
908 [(set_attr "length" "2")])
910 (define_insn "*x_plus_i_eq_0"
911 [(set (match_operand:SI 0 "register_operand" "=r")
912 (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
914 (match_operand:SI 2 "register_operand" "r")))
915 (clobber (reg:CC 0))]
917 "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
918 [(set_attr "length" "2")])
920 (define_insn "*x_minus_i_eq_0"
921 [(set (match_operand:SI 0 "register_operand" "=r")
922 (minus:SI (match_operand:SI 2 "register_operand" "r")
923 (eq:SI (match_operand:SI 1 "register_operand" "r")
925 (clobber (reg:CC 0))]
927 "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
928 [(set_attr "length" "2")])
930 ;; We can also do GEU and LTU directly, but these operate after a compare.
931 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
934 (define_insn "*sltu_insn"
935 [(set (match_operand:SI 0 "register_operand" "=r")
936 (ltu:SI (reg:CC 0) (const_int 0)))]
939 [(set_attr "type" "misc")])
941 (define_insn "*neg_sltu_insn"
942 [(set (match_operand:SI 0 "register_operand" "=r")
943 (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
946 [(set_attr "type" "misc")])
948 ;; ??? Combine should canonicalize these next two to the same pattern.
949 (define_insn "*neg_sltu_minus_x"
950 [(set (match_operand:SI 0 "register_operand" "=r")
951 (minus:SI (neg:SI (ltu:SI (reg:CC 0) (const_int 0)))
952 (match_operand:SI 1 "arith_operand" "rI")))]
955 [(set_attr "type" "unary")])
957 (define_insn "*neg_sltu_plus_x"
958 [(set (match_operand:SI 0 "register_operand" "=r")
959 (neg:SI (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
960 (match_operand:SI 1 "arith_operand" "rI"))))]
963 [(set_attr "type" "unary")])
965 (define_insn "*sgeu_insn"
966 [(set (match_operand:SI 0 "register_operand" "=r")
967 (geu:SI (reg:CC 0) (const_int 0)))]
970 [(set_attr "type" "misc")])
972 (define_insn "*neg_sgeu_insn"
973 [(set (match_operand:SI 0 "register_operand" "=r")
974 (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
977 [(set_attr "type" "misc")])
979 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
980 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
983 (define_insn "*sltu_plus_x"
984 [(set (match_operand:SI 0 "register_operand" "=r")
985 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
986 (match_operand:SI 1 "arith_operand" "rI")))]
989 [(set_attr "type" "unary")])
991 (define_insn "*sltu_plus_x_plus_y"
992 [(set (match_operand:SI 0 "register_operand" "=r")
993 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
994 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
995 (match_operand:SI 2 "arith_operand" "rI"))))]
999 (define_insn "*x_minus_sltu"
1000 [(set (match_operand:SI 0 "register_operand" "=r")
1001 (minus:SI (match_operand:SI 1 "register_operand" "r")
1002 (ltu:SI (reg:CC 0) (const_int 0))))]
1005 [(set_attr "type" "unary")])
1007 ;; ??? Combine should canonicalize these next two to the same pattern.
1008 (define_insn "*x_minus_y_minus_sltu"
1009 [(set (match_operand:SI 0 "register_operand" "=r")
1010 (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
1011 (match_operand:SI 2 "arith_operand" "rI"))
1012 (ltu:SI (reg:CC 0) (const_int 0))))]
1016 (define_insn "*x_minus_sltu_plus_y"
1017 [(set (match_operand:SI 0 "register_operand" "=r")
1018 (minus:SI (match_operand:SI 1 "register_operand" "r")
1019 (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
1020 (match_operand:SI 2 "arith_operand" "rI"))))]
1024 (define_insn "*sgeu_plus_x"
1025 [(set (match_operand:SI 0 "register_operand" "=r")
1026 (plus:SI (geu:SI (reg:CC 0) (const_int 0))
1027 (match_operand:SI 1 "register_operand" "r")))]
1030 [(set_attr "type" "unary")])
1032 (define_insn "*x_minus_sgeu"
1033 [(set (match_operand:SI 0 "register_operand" "=r")
1034 (minus:SI (match_operand:SI 1 "register_operand" "r")
1035 (geu:SI (reg:CC 0) (const_int 0))))]
1038 [(set_attr "type" "unary")])
1040 ;; Now we have the generic scc insns.
1041 ;; !v9: These will be done using a jump.
1042 ;; v9: Use conditional moves which are defined elsewhere.
1043 ;; We have to exclude the cases above, since we will not want combine to
1044 ;; turn something that does not require a jump into something that does.
1046 (define_insn "*scc_si"
1047 [(set (match_operand:SI 0 "register_operand" "=r")
1048 (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))]
1050 "* return output_scc_insn (operands, insn); "
1051 [(set_attr "type" "multi")
1052 (set_attr "length" "3")])
1054 (define_insn "*scc_di"
1055 [(set (match_operand:DI 0 "register_operand" "=r")
1056 (match_operator:DI 1 "noov_compare_op" [(reg 0) (const_int 0)]))]
1058 "* return output_scc_insn (operands, insn); "
1059 [(set_attr "type" "multi")
1060 (set_attr "length" "3")])
1062 ;; These control RTL generation for conditional jump insns
1064 ;; The quad-word fp compare library routines all return nonzero to indicate
1065 ;; true, which is different from the equivalent libgcc routines, so we must
1066 ;; handle them specially here.
1068 (define_expand "beq"
1070 (if_then_else (eq (match_dup 1) (const_int 0))
1071 (label_ref (match_operand 0 "" ""))
1076 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1077 && GET_CODE (sparc_compare_op0) == REG
1078 && GET_MODE (sparc_compare_op0) == DImode)
1080 emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1083 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1085 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1086 emit_jump_insn (gen_bne (operands[0]));
1089 operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1092 (define_expand "bne"
1094 (if_then_else (ne (match_dup 1) (const_int 0))
1095 (label_ref (match_operand 0 "" ""))
1100 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1101 && GET_CODE (sparc_compare_op0) == REG
1102 && GET_MODE (sparc_compare_op0) == DImode)
1104 emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1107 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1109 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1110 emit_jump_insn (gen_bne (operands[0]));
1113 operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1116 (define_expand "bgt"
1118 (if_then_else (gt (match_dup 1) (const_int 0))
1119 (label_ref (match_operand 0 "" ""))
1124 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1125 && GET_CODE (sparc_compare_op0) == REG
1126 && GET_MODE (sparc_compare_op0) == DImode)
1128 emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1131 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1133 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1134 emit_jump_insn (gen_bne (operands[0]));
1137 operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1140 (define_expand "bgtu"
1142 (if_then_else (gtu (match_dup 1) (const_int 0))
1143 (label_ref (match_operand 0 "" ""))
1147 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1150 (define_expand "blt"
1152 (if_then_else (lt (match_dup 1) (const_int 0))
1153 (label_ref (match_operand 0 "" ""))
1158 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1159 && GET_CODE (sparc_compare_op0) == REG
1160 && GET_MODE (sparc_compare_op0) == DImode)
1162 emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1165 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1167 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1168 emit_jump_insn (gen_bne (operands[0]));
1171 operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1174 (define_expand "bltu"
1176 (if_then_else (ltu (match_dup 1) (const_int 0))
1177 (label_ref (match_operand 0 "" ""))
1181 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1184 (define_expand "bge"
1186 (if_then_else (ge (match_dup 1) (const_int 0))
1187 (label_ref (match_operand 0 "" ""))
1192 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1193 && GET_CODE (sparc_compare_op0) == REG
1194 && GET_MODE (sparc_compare_op0) == DImode)
1196 emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1199 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1201 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1202 emit_jump_insn (gen_bne (operands[0]));
1205 operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1208 (define_expand "bgeu"
1210 (if_then_else (geu (match_dup 1) (const_int 0))
1211 (label_ref (match_operand 0 "" ""))
1215 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1218 (define_expand "ble"
1220 (if_then_else (le (match_dup 1) (const_int 0))
1221 (label_ref (match_operand 0 "" ""))
1226 if (TARGET_V9 && sparc_compare_op1 == const0_rtx
1227 && GET_CODE (sparc_compare_op0) == REG
1228 && GET_MODE (sparc_compare_op0) == DImode)
1230 emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1233 else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1235 emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1236 emit_jump_insn (gen_bne (operands[0]));
1239 operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1242 (define_expand "bleu"
1244 (if_then_else (leu (match_dup 1) (const_int 0))
1245 (label_ref (match_operand 0 "" ""))
1249 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1252 ;; Now match both normal and inverted jump.
1254 (define_insn "*normal_branch"
1256 (if_then_else (match_operator 0 "noov_compare_op"
1257 [(reg 0) (const_int 0)])
1258 (label_ref (match_operand 1 "" ""))
1263 return output_cbranch (operands[0], 0, 1, 0,
1264 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1267 [(set_attr "type" "branch")])
1269 (define_insn "*inverted_branch"
1271 (if_then_else (match_operator 0 "noov_compare_op"
1272 [(reg 0) (const_int 0)])
1274 (label_ref (match_operand 1 "" ""))))]
1278 return output_cbranch (operands[0], 0, 1, 1,
1279 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1282 [(set_attr "type" "branch")])
1284 (define_insn "*normal_fp_branch_sp64"
1286 (if_then_else (match_operator 0 "comparison_operator"
1287 [(match_operand:CCFP 1 "ccfp_reg_operand" "c")
1289 (label_ref (match_operand 2 "" ""))
1294 return output_cbranch (operands[0], operands[1], 2, 0,
1295 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1298 [(set_attr "type" "branch")])
1300 (define_insn "*inverted_fp_branch_sp64"
1302 (if_then_else (match_operator 0 "comparison_operator"
1303 [(match_operand:CCFP 1 "ccfp_reg_operand" "c")
1306 (label_ref (match_operand 2 "" ""))))]
1310 return output_cbranch (operands[0], operands[1], 2, 1,
1311 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1314 [(set_attr "type" "branch")])
1316 (define_insn "*normal_fpe_branch_sp64"
1318 (if_then_else (match_operator 0 "comparison_operator"
1319 [(match_operand:CCFPE 1 "ccfp_reg_operand" "c")
1321 (label_ref (match_operand 2 "" ""))
1326 return output_cbranch (operands[0], operands[1], 2, 0,
1327 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1330 [(set_attr "type" "branch")])
1332 (define_insn "*inverted_fpe_branch_sp64"
1334 (if_then_else (match_operator 0 "comparison_operator"
1335 [(match_operand:CCFPE 1 "ccfp_reg_operand" "c")
1338 (label_ref (match_operand 2 "" ""))))]
1342 return output_cbranch (operands[0], operands[1], 2, 1,
1343 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1346 [(set_attr "type" "branch")])
1348 ;; Sparc V9-specific jump insns. None of these are guaranteed to be
1349 ;; in the architecture.
1351 ;; There are no 32 bit brreg insns.
1353 (define_insn "*normal_int_branch_sp64"
1355 (if_then_else (match_operator 0 "v9_regcmp_op"
1356 [(match_operand:DI 1 "register_operand" "r")
1358 (label_ref (match_operand 2 "" ""))
1363 return output_v9branch (operands[0], 1, 2, 0,
1364 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1367 [(set_attr "type" "branch")])
1369 (define_insn "*inverted_int_branch_sp64"
1371 (if_then_else (match_operator 0 "v9_regcmp_op"
1372 [(match_operand:DI 1 "register_operand" "r")
1375 (label_ref (match_operand 2 "" ""))))]
1379 return output_v9branch (operands[0], 1, 2, 1,
1380 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1383 [(set_attr "type" "branch")])
1385 ;; Esoteric move insns (lo_sum, high, pic).
1387 (define_insn "*lo_sum_si"
1388 [(set (match_operand:SI 0 "register_operand" "=r")
1389 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1390 (match_operand:SI 2 "immediate_operand" "in")))]
1392 ;; V9 needs "add" because of the code models. We still use "or" for v8
1393 ;; so we can compare the old compiler with the new.
1394 "* return TARGET_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1395 ;; Need to set length for this arith insn because operand2
1396 ;; is not an "arith_operand".
1397 [(set_attr "length" "1")])
1399 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1400 ;; confuse them with real addresses.
1401 (define_insn "*pic_lo_sum_si"
1402 [(set (match_operand:SI 0 "register_operand" "=r")
1403 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1404 (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
1406 ;; V9 needs "add" because of the code models. We still use "or" for v8
1407 ;; so we can compare the old compiler with the new.
1408 "* return TARGET_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1409 ;; Need to set length for this arith insn because operand2
1410 ;; is not an "arith_operand".
1411 [(set_attr "length" "1")])
1413 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1414 ;; confuse them with real addresses.
1415 (define_insn "*pic_sethi_si"
1416 [(set (match_operand:SI 0 "register_operand" "=r")
1417 (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1419 "sethi %%hi(%a1),%0"
1420 [(set_attr "type" "move")
1421 (set_attr "length" "1")])
1423 (define_insn "*sethi_si"
1424 [(set (match_operand:SI 0 "register_operand" "=r")
1425 (high:SI (match_operand 1 "" "")))]
1427 "sethi %%hi(%a1),%0"
1428 [(set_attr "type" "move")
1429 (set_attr "length" "1")])
1431 (define_insn "*sethi_hi"
1432 [(set (match_operand:HI 0 "register_operand" "=r")
1433 (high:HI (match_operand 1 "" "")))]
1435 "sethi %%hi(%a1),%0"
1436 [(set_attr "type" "move")
1437 (set_attr "length" "1")])
1439 ;; Special pic pattern, for loading the address of a label into a register.
1440 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
1443 (define_insn "*move_pic_label_si"
1444 [(set (match_operand:SI 0 "register_operand" "=r")
1445 (match_operand:SI 1 "move_pic_label" "i"))
1446 (set (reg:SI 15) (pc))]
1448 "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
1449 [(set_attr "type" "multi")
1450 (set_attr "length" "4")])
1452 ;; v9 special pic pattern, for loading the address of a label into a register.
1454 (define_insn "*move_pic_label_di"
1455 [(set (match_operand:DI 0 "register_operand" "=r")
1456 (match_operand:DI 1 "move_pic_label" "i"))
1457 (set (reg:DI 15) (pc))]
1459 "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
1460 [(set_attr "type" "multi")
1461 (set_attr "length" "4")])
1463 (define_insn "*lo_sum_di_sp32"
1464 [(set (match_operand:DI 0 "register_operand" "=r")
1465 (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1466 (match_operand:DI 2 "immediate_operand" "in")))]
1470 /* Don't output a 64 bit constant, since we can't trust the assembler to
1471 handle it correctly. */
1472 if (GET_CODE (operands[2]) == CONST_DOUBLE)
1473 operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
1474 return \"or %R1,%%lo(%a2),%R0\";
1476 ;; Need to set length for this arith insn because operand2
1477 ;; is not an "arith_operand".
1478 [(set_attr "length" "1")])
1480 ;; ??? Gas does not handle %lo(DI), so we use the same code for ! TARGET_V9.
1481 ;; ??? The previous comment is obsolete.
1482 ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
1484 (define_insn "*lo_sum_di_sp64"
1485 [(set (match_operand:DI 0 "register_operand" "=r")
1486 (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1487 (match_operand:DI 2 "immediate_operand" "in")))]
1491 /* Don't output a 64 bit constant, since we can't trust the assembler to
1492 handle it correctly. */
1493 if (GET_CODE (operands[2]) == CONST_DOUBLE)
1494 operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
1495 /* Note that we use add here. This is important because Medium/Anywhere
1496 code model support depends on it. */
1497 return \"add %1,%%lo(%a2),%0\";
1499 ;; Need to set length for this arith insn because operand2
1500 ;; is not an "arith_operand".
1501 [(set_attr "length" "1")])
1503 (define_insn "*sethi_di_sp32"
1504 [(set (match_operand:DI 0 "register_operand" "=r")
1505 (high:DI (match_operand 1 "" "")))]
1506 "! TARGET_V9 && check_pic (1)"
1509 rtx op0 = operands[0];
1510 rtx op1 = operands[1];
1512 if (GET_CODE (op1) == CONST_INT)
1514 operands[0] = operand_subword (op0, 1, 0, DImode);
1515 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1517 operands[0] = operand_subword (op0, 0, 0, DImode);
1518 if (INTVAL (op1) < 0)
1519 return \"mov -1,%0\";
1521 return \"mov 0,%0\";
1523 else if (GET_CODE (op1) == CONST_DOUBLE)
1525 operands[0] = operand_subword (op0, 1, 0, DImode);
1526 operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
1527 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1529 operands[0] = operand_subword (op0, 0, 0, DImode);
1530 operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
1531 return singlemove_string (operands);
1537 [(set_attr "type" "move")
1538 (set_attr "length" "2")])
1540 ;;; ??? This pattern originally clobbered a scratch register. However, this
1541 ;;; is invalid, the movdi pattern may not use a temp register because it
1542 ;;; may be called from reload to reload a DImode value. In that case, we
1543 ;;; end up with a scratch register that never gets allocated. To avoid this,
1544 ;;; we use global register 1 which is never otherwise used by gcc as a temp.
1545 ;;; The correct solution here might be to force DImode constants to memory,
1546 ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
1547 ;;; 1 will then no longer need to be considered a fixed reg.
1549 ;;; Gas doesn't have any 64 bit constant support, so don't use %uhi and %ulo
1550 ;;; on constants. Symbols have to be handled by the linker, so we must use
1551 ;;; %uhi and %ulo for them, but gas will handle these correctly.
1552 ;;; ??? This comment is obsolete, gas handles them now.
1554 (define_insn "*sethi_di_sp64"
1555 [(set (match_operand:DI 0 "register_operand" "=r")
1556 (high:DI (match_operand 1 "const_double_operand" "")))
1557 (clobber (reg:DI 1))]
1558 "TARGET_V9 && check_pic (1)"
1563 split_double (operands[1], &high, &low);
1565 if (high == const0_rtx)
1568 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1573 output_asm_insn (singlemove_string (operands), operands);
1576 output_asm_insn (\"sllx %0,32,%0\", operands);
1577 if (low != const0_rtx)
1578 output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1581 [(set_attr "type" "move")
1582 (set_attr "length" "5")])
1584 ;; Most of the required support for the various code models is here.
1585 ;; We can do this because sparcs need the high insn to load the address. We
1586 ;; just need to get high to do the right thing for each code model. Then each
1587 ;; uses the same "%X+%lo(...)" in the load/store insn.
1589 ;; When TARGET_MEDLOW, assume that the upper 32 bits of symbol addresses are
1591 ;; When TARGET_MEDANY, the upper 32 bits of function addresses are 0.
1592 ;; The data segment has a maximum size of 32 bits, but may be located anywhere.
1593 ;; MEDANY_BASE_REG contains the start address, currently %g4.
1594 ;; When TARGET_FULLANY, symbolic addresses are 64 bits.
1596 (define_insn "*sethi_di_medlow"
1597 [(set (match_operand:DI 0 "register_operand" "=r")
1598 (high:DI (match_operand 1 "" "")))
1599 ;; ??? Why the clobber?
1600 (clobber (reg:DI 1))]
1601 "TARGET_MEDLOW && check_pic (1)"
1602 "sethi %%hi(%a1),%0"
1603 [(set_attr "type" "move")
1604 (set_attr "length" "1")])
1606 ;; WARNING: %0 gets %hi(%1)+%g4.
1607 ;; You cannot OR in %lo(%1), it must be added in.
1609 (define_insn "*sethi_di_medany_data"
1610 [(set (match_operand:DI 0 "register_operand" "=r")
1611 (high:DI (match_operand 1 "data_segment_operand" "")))
1612 ;; ??? Why the clobber?
1613 (clobber (reg:DI 1))]
1614 "TARGET_MEDANY && check_pic (1)"
1615 "sethi %%hi(%a1),%0; add %0,%%g4,%0"
1616 [(set_attr "type" "move")
1617 (set_attr "length" "2")])
1619 (define_insn "*sethi_di_medany_text"
1620 [(set (match_operand:DI 0 "register_operand" "=r")
1621 (high:DI (match_operand 1 "text_segment_operand" "")))
1622 ;; ??? Why the clobber?
1623 (clobber (reg:DI 1))]
1624 "TARGET_MEDANY && check_pic (1)"
1625 "sethi %%hi(%a1),%0"
1626 [(set_attr "type" "move")
1627 (set_attr "length" "1")])
1629 (define_insn "*sethi_di_fullany"
1630 [(set (match_operand:DI 0 "register_operand" "=r")
1631 (high:DI (match_operand 1 "" "")))
1632 (clobber (reg:DI 1))]
1633 "TARGET_FULLANY && check_pic (1)"
1634 "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1635 [(set_attr "type" "move")
1636 (set_attr "length" "5")])
1638 ;; Move instructions
1640 (define_expand "movqi"
1641 [(set (match_operand:QI 0 "general_operand" "")
1642 (match_operand:QI 1 "general_operand" ""))]
1646 if (emit_move_sequence (operands, QImode))
1650 (define_insn "*movqi_insn"
1651 [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1652 (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1653 "register_operand (operands[0], QImode)
1654 || register_operand (operands[1], QImode)
1655 || operands[1] == const0_rtx"
1661 [(set_attr "type" "move,move,load,store")
1662 (set_attr "length" "*,1,*,1")])
1664 (define_insn "*lo_sum_qi"
1665 [(set (match_operand:QI 0 "register_operand" "=r")
1666 (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1667 (match_operand 2 "immediate_operand" "in")) 0))]
1669 "or %1,%%lo(%a2),%0"
1670 [(set_attr "length" "1")])
1672 (define_insn "*store_qi"
1673 [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1674 (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1675 (clobber (match_scratch:SI 2 "=&r"))]
1676 "(reload_completed || reload_in_progress) && ! TARGET_PTR64"
1677 "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1678 [(set_attr "type" "store")
1679 (set_attr "length" "2")])
1681 (define_expand "movhi"
1682 [(set (match_operand:HI 0 "general_operand" "")
1683 (match_operand:HI 1 "general_operand" ""))]
1687 if (emit_move_sequence (operands, HImode))
1691 (define_insn "*movhi_insn"
1692 [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1693 (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
1694 "register_operand (operands[0], HImode)
1695 || register_operand (operands[1], HImode)
1696 || operands[1] == const0_rtx"
1702 [(set_attr "type" "move,move,load,store")
1703 (set_attr "length" "*,1,*,1")])
1705 (define_insn "*lo_sum_hi"
1706 [(set (match_operand:HI 0 "register_operand" "=r")
1707 (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
1708 (match_operand 2 "immediate_operand" "in")))]
1710 "or %1,%%lo(%a2),%0"
1711 [(set_attr "length" "1")])
1713 (define_insn "*store_hi"
1714 [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
1715 (match_operand:HI 1 "reg_or_0_operand" "rJ"))
1716 (clobber (match_scratch:SI 2 "=&r"))]
1717 "(reload_completed || reload_in_progress) && ! TARGET_PTR64"
1718 "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
1719 [(set_attr "type" "store")
1720 (set_attr "length" "2")])
1722 (define_expand "movsi"
1723 [(set (match_operand:SI 0 "general_operand" "")
1724 (match_operand:SI 1 "general_operand" ""))]
1728 if (emit_move_sequence (operands, SImode))
1732 ;; We must support both 'r' and 'f' registers here, because combine may
1733 ;; convert SFmode hard registers to SImode hard registers when simplifying
1736 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
1737 ;; problems with register allocation. Reload might try to put an integer
1738 ;; in an fp register, or an fp number is an integer register.
1740 (define_insn "*movsi_insn"
1741 [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
1742 (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
1743 "register_operand (operands[0], SImode)
1744 || register_operand (operands[1], SImode)
1745 || operands[1] == const0_rtx"
1754 [(set_attr "type" "move,fp,move,load,load,store,store")
1755 (set_attr "length" "*,*,1,*,*,*,*")])
1757 (define_insn "*store_si"
1758 [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
1759 (match_operand:SI 1 "reg_or_0_operand" "rJ"))
1760 (clobber (match_scratch:SI 2 "=&r"))]
1761 "(reload_completed || reload_in_progress) && ! TARGET_PTR64"
1762 "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1763 [(set_attr "type" "store")
1764 (set_attr "length" "2")])
1766 (define_expand "movdi"
1767 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1768 (match_operand:DI 1 "general_operand" ""))]
1772 if (emit_move_sequence (operands, DImode))
1776 (define_insn "*movdi_sp32_insn"
1777 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
1778 (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
1780 && (register_operand (operands[0], DImode)
1781 || register_operand (operands[1], DImode)
1782 || operands[1] == const0_rtx)"
1785 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1786 return output_fp_move_double (operands);
1787 return output_move_double (operands);
1789 [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
1790 (set_attr "length" "2,1,1,3,3,3,2,3,3")])
1792 ;;; ??? The trick used below can be extended to load any negative 32 bit
1793 ;;; constant in two instructions. Currently the compiler will use HIGH/LO_SUM
1794 ;;; for anything not matching the HIK constraints, which results in 5
1795 ;;; instructions. Positive 32 bit constants can be loaded in the obvious way
1796 ;;; with sethi/ori. To extend the trick, in the xor instruction, use
1797 ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
1798 ;;; This needs the original value of operands[1], not the inverted value.
1800 (define_insn "*movdi_sp64_insn"
1801 [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
1802 (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
1804 && (register_operand (operands[0], DImode)
1805 || register_operand (operands[1], DImode)
1806 || operands[1] == const0_rtx)"
1809 switch (which_alternative)
1812 return \"mov %1,%0\";
1814 /* Sethi does not sign extend, so we must use a little trickery
1815 to use it for negative numbers. Invert the constant before
1816 loading it in, then use a xor immediate to invert the loaded bits
1817 (along with the upper 32 bits) to the desired constant. This
1818 works because the sethi and immediate fields overlap. */
1820 if ((INTVAL (operands[1]) & 0x80000000) == 0)
1821 return \"sethi %%hi(%a1),%0\";
1824 operands[1] = gen_rtx (CONST_INT, VOIDmode,
1825 ~ INTVAL (operands[1]));
1826 output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1827 /* The low 10 bits are already zero, but invert the rest.
1828 Assemblers don't accept 0x1c00, so use -0x400 instead. */
1829 return \"xor %0,-0x400,%0\";
1832 return \"ldx %1,%0\";
1834 return \"stx %r1,%0\";
1836 return \"mov %1,%0\";
1838 return \"ldd %1,%0\";
1840 return \"std %1,%0\";
1843 [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
1844 (set_attr "length" "1,2,1,1,1,1,1")])
1846 ;; ??? There's no symbolic (set (mem:DI ...) ...).
1847 ;; Experimentation with v9 suggested one isn't needed.
1849 ;; Block move insns.
1851 ;; ??? We get better code without it. See output_block_move in sparc.c.
1853 ;; The definition of this insn does not really explain what it does,
1854 ;; but it should suffice
1855 ;; that anything generated as this insn will be recognized as one
1856 ;; and that it will not successfully combine with anything.
1857 ;(define_expand "movstrsi"
1858 ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
1859 ; (mem:BLK (match_operand:BLK 1 "general_operand" "")))
1860 ; (use (match_operand:SI 2 "nonmemory_operand" ""))
1861 ; (use (match_operand:SI 3 "immediate_operand" ""))
1862 ; (clobber (match_dup 0))
1863 ; (clobber (match_dup 1))
1864 ; (clobber (match_scratch:SI 4 ""))
1865 ; (clobber (reg:SI 0))
1866 ; (clobber (reg:SI 1))])]
1870 ; /* If the size isn't known, don't emit inline code. output_block_move
1871 ; would output code that's much slower than the library function.
1872 ; Also don't output code for large blocks. */
1873 ; if (GET_CODE (operands[2]) != CONST_INT
1874 ; || GET_CODE (operands[3]) != CONST_INT
1875 ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
1878 ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1879 ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1880 ; operands[2] = force_not_mem (operands[2]);
1883 ;(define_insn "*block_move_insn"
1884 ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
1885 ; (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
1886 ; (use (match_operand:SI 2 "nonmemory_operand" "rn"))
1887 ; (use (match_operand:SI 3 "immediate_operand" "i"))
1888 ; (clobber (match_dup 0))
1889 ; (clobber (match_dup 1))
1890 ; (clobber (match_scratch:SI 4 "=&r"))
1891 ; (clobber (reg:SI 0))
1892 ; (clobber (reg:SI 1))]
1894 ; "* return output_block_move (operands);"
1895 ; [(set_attr "type" "multi")
1896 ; (set_attr "length" "6")])
1898 ;; Floating point move insns
1900 ;; This pattern forces (set (reg:SF ...) (const_double ...))
1901 ;; to be reloaded by putting the constant into memory.
1902 ;; It must come before the more general movsf pattern.
1903 (define_insn "*movsf_const_insn"
1904 [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
1905 (match_operand:SF 1 "" "?F,m,G"))]
1906 "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1909 switch (which_alternative)
1912 return singlemove_string (operands);
1914 return \"ld %1,%0\";
1916 return \"st %%g0,%0\";
1919 [(set_attr "type" "load,fpload,store")
1920 (set_attr "length" "2,1,1")])
1922 (define_expand "movsf"
1923 [(set (match_operand:SF 0 "general_operand" "")
1924 (match_operand:SF 1 "general_operand" ""))]
1928 if (emit_move_sequence (operands, SFmode))
1932 (define_insn "*movsf_insn"
1933 [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
1934 (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
1936 && (register_operand (operands[0], SFmode)
1937 || register_operand (operands[1], SFmode))"
1945 [(set_attr "type" "fp,move,fpload,load,fpstore,store")])
1947 ;; Exactly the same as above, except that all `f' cases are deleted.
1948 ;; This is necessary to prevent reload from ever trying to use a `f' reg
1951 (define_insn "*movsf_no_f_insn"
1952 [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
1953 (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
1955 && (register_operand (operands[0], SFmode)
1956 || register_operand (operands[1], SFmode))"
1961 [(set_attr "type" "move,load,store")])
1963 (define_insn "*store_sf"
1964 [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
1965 (match_operand:SF 1 "reg_or_0_operand" "rfG"))
1966 (clobber (match_scratch:SI 2 "=&r"))]
1967 "(reload_completed || reload_in_progress) && ! TARGET_PTR64"
1968 "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1969 [(set_attr "type" "store")
1970 (set_attr "length" "2")])
1972 ;; This pattern forces (set (reg:DF ...) (const_double ...))
1973 ;; to be reloaded by putting the constant into memory.
1974 ;; It must come before the more general movdf pattern.
1976 (define_insn "*movdf_const_insn"
1977 [(set (match_operand:DF 0 "general_operand" "=?r,e,o")
1978 (match_operand:DF 1 "" "?F,m,G"))]
1979 "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1982 switch (which_alternative)
1985 return output_move_double (operands);
1987 return output_fp_move_double (operands);
1991 return \"stx %%g0,%0\";
1995 operands[1] = adj_offsettable_operand (operands[0], 4);
1996 return \"st %%g0,%0\;st %%g0,%1\";
2000 [(set_attr "type" "load,fpload,store")
2001 (set_attr "length" "3,3,3")])
2003 (define_expand "movdf"
2004 [(set (match_operand:DF 0 "general_operand" "")
2005 (match_operand:DF 1 "general_operand" ""))]
2009 if (emit_move_sequence (operands, DFmode))
2013 (define_insn "*movdf_insn"
2014 [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r")
2015 (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))]
2017 && (register_operand (operands[0], DFmode)
2018 || register_operand (operands[1], DFmode))"
2021 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2022 return output_fp_move_double (operands);
2023 return output_move_double (operands);
2025 [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
2026 (set_attr "length" "1,1,2,2,3,3,3,3")])
2028 ;; Exactly the same as above, except that all `e' cases are deleted.
2029 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2032 (define_insn "*movdf_no_e_insn"
2033 [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
2034 (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
2036 && (register_operand (operands[0], DFmode)
2037 || register_operand (operands[1], DFmode))"
2038 "* return output_move_double (operands);"
2039 [(set_attr "type" "store,load,move,store,load")
2040 (set_attr "length" "1,1,2,3,3")])
2042 ;; Must handle overlapping registers here, since parameters can be unaligned
2044 ;; ??? Do we need a v9 version of this?
2046 [(set (match_operand:DF 0 "register_operand" "")
2047 (match_operand:DF 1 "register_operand" ""))]
2048 "! TARGET_V9 && reload_completed"
2049 [(set (match_dup 2) (match_dup 3))
2050 (set (match_dup 4) (match_dup 5))]
2053 rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
2054 rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
2056 if (REGNO (first_set) == REGNO (second_use))
2058 operands[2] = operand_subword (operands[0], 1, 0, DFmode);
2059 operands[3] = second_use;
2060 operands[4] = first_set;
2061 operands[5] = operand_subword (operands[1], 0, 0, DFmode);
2065 operands[2] = first_set;
2066 operands[3] = operand_subword (operands[1], 0, 0, DFmode);
2067 operands[4] = operand_subword (operands[0], 1, 0, DFmode);
2068 operands[5] = second_use;
2072 (define_insn "*store_df"
2073 [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
2074 (match_operand:DF 1 "reg_or_0_operand" "re,G"))
2075 (clobber (match_scratch:SI 2 "=&r,&r"))]
2076 "(reload_completed || reload_in_progress) && ! TARGET_PTR64"
2079 output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2080 if (which_alternative == 0)
2081 return \"std %1,[%2+%%lo(%a0)]\";
2083 return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
2085 [(set_attr "type" "store")
2086 (set_attr "length" "3")])
2088 ;; This pattern forces (set (reg:TF ...) (const_double ...))
2089 ;; to be reloaded by putting the constant into memory.
2090 ;; It must come before the more general movtf pattern.
2091 (define_insn "*movtf_const_insn"
2092 [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
2093 (match_operand:TF 1 "" "?F,m,G"))]
2094 "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2097 switch (which_alternative)
2100 return output_move_quad (operands);
2102 return output_fp_move_quad (operands);
2106 operands[1] = adj_offsettable_operand (operands[0], 8);
2107 return \"stx %%g0,%0\;stx %%g0,%1\";
2111 /* ??? Do we run off the end of the array here? */
2112 operands[1] = adj_offsettable_operand (operands[0], 4);
2113 operands[2] = adj_offsettable_operand (operands[0], 8);
2114 operands[3] = adj_offsettable_operand (operands[0], 12);
2115 return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
2119 [(set_attr "type" "load,fpload,store")
2120 (set_attr "length" "5,5,5")])
2122 (define_expand "movtf"
2123 [(set (match_operand:TF 0 "general_operand" "")
2124 (match_operand:TF 1 "general_operand" ""))]
2128 if (emit_move_sequence (operands, TFmode))
2132 (define_insn "*movtf_insn"
2133 [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r")
2134 (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))]
2136 && (register_operand (operands[0], TFmode)
2137 || register_operand (operands[1], TFmode))"
2140 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2141 return output_fp_move_quad (operands);
2142 return output_move_quad (operands);
2144 [(set_attr "type" "fp,move,fpstore,store,fpload,load")
2145 (set_attr "length" "4,4,5,5,5,5")])
2147 ;; Exactly the same as above, except that all `e' cases are deleted.
2148 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2151 (define_insn "*movtf_no_e_insn"
2152 [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
2153 (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
2155 && (register_operand (operands[0], TFmode)
2156 || register_operand (operands[1], TFmode))"
2159 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2160 return output_fp_move_quad (operands);
2161 return output_move_quad (operands);
2163 [(set_attr "type" "move,store,load")
2164 (set_attr "length" "4,5,5")])
2166 ;; This is disabled because it does not work. Long doubles have only 8
2167 ;; byte alignment. Adding an offset of 8 or 12 to an 8 byte aligned %lo may
2168 ;; cause it to overflow. See also GO_IF_LEGITIMATE_ADDRESS.
2169 (define_insn "*store_tf"
2170 [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
2171 (match_operand:TF 1 "reg_or_0_operand" "re,G"))
2172 (clobber (match_scratch:SI 2 "=&r,&r"))]
2173 "0 && (reload_completed || reload_in_progress) && ! TARGET_PTR64"
2176 output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2177 if (which_alternative == 0)
2178 return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
2180 return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
2182 [(set_attr "type" "store")
2183 (set_attr "length" "5")])
2185 ;; Sparc V9 conditional move instructions.
2187 ;; We can handle larger constants here for some flavors, but for now we play
2188 ;; it safe and only allow those constants supported by all flavours.
2190 (define_expand "movsicc"
2191 [(set (match_operand:SI 0 "register_operand" "")
2192 (if_then_else (match_operand 1 "comparison_operator" "")
2193 (match_operand:SI 2 "arith10_operand" "")
2194 (match_operand:SI 3 "register_operand" "")))]
2198 enum rtx_code code = GET_CODE (operands[1]);
2200 if (sparc_compare_op1 == const0_rtx
2201 && GET_CODE (sparc_compare_op0) == REG
2202 && GET_MODE (sparc_compare_op0) == DImode
2203 && v9_regcmp_p (code))
2205 operands[1] = gen_rtx (code, DImode,
2206 sparc_compare_op0, sparc_compare_op1);
2210 rtx cc_reg = gen_compare_reg (code,
2211 sparc_compare_op0, sparc_compare_op1);
2212 operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2216 (define_expand "movdicc"
2217 [(set (match_operand:DI 0 "register_operand" "")
2218 (if_then_else (match_operand 1 "comparison_operator" "")
2219 (match_operand:DI 2 "arith10_operand" "")
2220 (match_operand:DI 3 "register_operand" "")))]
2224 enum rtx_code code = GET_CODE (operands[1]);
2226 if (sparc_compare_op1 == const0_rtx
2227 && GET_CODE (sparc_compare_op0) == REG
2228 && GET_MODE (sparc_compare_op0) == DImode
2229 && v9_regcmp_p (code))
2231 operands[1] = gen_rtx (code, DImode,
2232 sparc_compare_op0, sparc_compare_op1);
2236 rtx cc_reg = gen_compare_reg (code,
2237 sparc_compare_op0, sparc_compare_op1);
2238 operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2242 (define_expand "movsfcc"
2243 [(set (match_operand:SF 0 "register_operand" "")
2244 (if_then_else (match_operand 1 "comparison_operator" "")
2245 (match_operand:SF 2 "register_operand" "")
2246 (match_operand:SF 3 "register_operand" "")))]
2250 enum rtx_code code = GET_CODE (operands[1]);
2252 if (sparc_compare_op1 == const0_rtx
2253 && GET_CODE (sparc_compare_op0) == REG
2254 && GET_MODE (sparc_compare_op0) == DImode
2255 && v9_regcmp_p (code))
2257 operands[1] = gen_rtx (code, DImode,
2258 sparc_compare_op0, sparc_compare_op1);
2262 rtx cc_reg = gen_compare_reg (code,
2263 sparc_compare_op0, sparc_compare_op1);
2264 operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2268 (define_expand "movdfcc"
2269 [(set (match_operand:DF 0 "register_operand" "")
2270 (if_then_else (match_operand 1 "comparison_operator" "")
2271 (match_operand:DF 2 "register_operand" "")
2272 (match_operand:DF 3 "register_operand" "")))]
2276 enum rtx_code code = GET_CODE (operands[1]);
2278 if (sparc_compare_op1 == const0_rtx
2279 && GET_CODE (sparc_compare_op0) == REG
2280 && GET_MODE (sparc_compare_op0) == DImode
2281 && v9_regcmp_p (code))
2283 operands[1] = gen_rtx (code, DImode,
2284 sparc_compare_op0, sparc_compare_op1);
2288 rtx cc_reg = gen_compare_reg (code,
2289 sparc_compare_op0, sparc_compare_op1);
2290 operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2294 (define_expand "movtfcc"
2295 [(set (match_operand:TF 0 "register_operand" "")
2296 (if_then_else (match_operand 1 "comparison_operator" "")
2297 (match_operand:TF 2 "register_operand" "")
2298 (match_operand:TF 3 "register_operand" "")))]
2302 enum rtx_code code = GET_CODE (operands[1]);
2304 if (sparc_compare_op1 == const0_rtx
2305 && GET_CODE (sparc_compare_op0) == REG
2306 && GET_MODE (sparc_compare_op0) == DImode
2307 && v9_regcmp_p (code))
2309 operands[1] = gen_rtx (code, DImode,
2310 sparc_compare_op0, sparc_compare_op1);
2314 rtx cc_reg = gen_compare_reg (code,
2315 sparc_compare_op0, sparc_compare_op1);
2316 operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2320 /* Conditional move define_insns. */
2322 (define_insn "*movsi_cc_sp64"
2323 [(set (match_operand:SI 0 "register_operand" "=r")
2324 (if_then_else (match_operator 1 "comparison_operator"
2325 [(reg:CC 0) (const_int 0)])
2326 (match_operand:SI 2 "arith11_operand" "ri")
2327 (match_operand:SI 3 "register_operand" "0")))]
2329 "mov%C1 %%icc,%2,%0"
2330 [(set_attr "type" "cmove")])
2332 (define_insn "*movdi_cc_sp64"
2333 [(set (match_operand:DI 0 "register_operand" "=r")
2334 (if_then_else (match_operator 1 "comparison_operator"
2335 [(reg:CC 0) (const_int 0)])
2336 (match_operand:DI 2 "arith11_double_operand" "rHI")
2337 (match_operand:DI 3 "register_operand" "0")))]
2339 "mov%C1 %%icc,%2,%0"
2340 [(set_attr "type" "cmove")])
2342 (define_insn "*movsi_ccx_sp64"
2343 [(set (match_operand:SI 0 "register_operand" "=r")
2344 (if_then_else (match_operator 1 "comparison_operator"
2345 [(reg:CCX 0) (const_int 0)])
2346 (match_operand:SI 2 "arith11_operand" "ri")
2347 (match_operand:SI 3 "register_operand" "0")))]
2349 "mov%C1 %%xcc,%2,%0"
2350 [(set_attr "type" "cmove")])
2352 (define_insn "*movdi_ccx_sp64"
2353 [(set (match_operand:DI 0 "register_operand" "=r")
2354 (if_then_else (match_operator 1 "comparison_operator"
2355 [(reg:CCX 0) (const_int 0)])
2356 (match_operand:DI 2 "arith11_double_operand" "rHI")
2357 (match_operand:DI 3 "register_operand" "0")))]
2359 "mov%C1 %%xcc,%2,%0"
2360 [(set_attr "type" "cmove")])
2362 (define_insn "*movsi_ccfp_sp64"
2363 [(set (match_operand:SI 0 "register_operand" "=r")
2364 (if_then_else (match_operator 1 "comparison_operator"
2365 [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
2367 (match_operand:SI 3 "arith11_operand" "ri")
2368 (match_operand:SI 4 "register_operand" "0")))]
2371 [(set_attr "type" "cmove")])
2373 (define_insn "*movsi_ccfpe_sp64"
2374 [(set (match_operand:SI 0 "register_operand" "=r")
2375 (if_then_else (match_operator 1 "comparison_operator"
2376 [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
2378 (match_operand:SI 3 "arith11_operand" "ri")
2379 (match_operand:SI 4 "register_operand" "0")))]
2382 [(set_attr "type" "cmove")])
2384 (define_insn "*movdi_ccfp_sp64"
2385 [(set (match_operand:DI 0 "register_operand" "=r")
2386 (if_then_else (match_operator 1 "comparison_operator"
2387 [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
2389 (match_operand:DI 3 "arith11_double_operand" "rHI")
2390 (match_operand:DI 4 "register_operand" "0")))]
2393 [(set_attr "type" "cmove")])
2395 (define_insn "*movdi_ccfpe_sp64"
2396 [(set (match_operand:DI 0 "register_operand" "=r")
2397 (if_then_else (match_operator 1 "comparison_operator"
2398 [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
2400 (match_operand:DI 3 "arith11_double_operand" "rHI")
2401 (match_operand:DI 4 "register_operand" "0")))]
2404 [(set_attr "type" "cmove")])
2406 (define_insn "*movsi_cc_reg_sp64"
2407 [(set (match_operand:SI 0 "register_operand" "=r")
2408 (if_then_else (match_operator 1 "v9_regcmp_op"
2409 [(match_operand:DI 2 "register_operand" "r")
2411 (match_operand:SI 3 "arith10_operand" "ri")
2412 (match_operand:SI 4 "register_operand" "0")))]
2415 [(set_attr "type" "cmove")])
2417 (define_insn "*movdi_cc_reg_sp64"
2418 [(set (match_operand:DI 0 "register_operand" "=r")
2419 (if_then_else (match_operator 1 "v9_regcmp_op"
2420 [(match_operand:DI 2 "register_operand" "r")
2422 (match_operand:DI 3 "arith10_double_operand" "ri")
2423 (match_operand:DI 4 "register_operand" "0")))]
2426 [(set_attr "type" "cmove")])
2428 (define_insn "*movsf_cc_reg_sp64"
2429 [(set (match_operand:SF 0 "register_operand" "=f")
2430 (if_then_else (match_operator 1 "v9_regcmp_op"
2431 [(match_operand:DI 2 "register_operand" "r")
2433 (match_operand:SF 3 "register_operand" "f")
2434 (match_operand:SF 4 "register_operand" "0")))]
2435 "TARGET_V9 && TARGET_FPU"
2436 "fmovrs%D1 %2,%r3,%0"
2437 [(set_attr "type" "cmove")])
2439 (define_insn "*movdf_cc_reg_sp64"
2440 [(set (match_operand:DF 0 "register_operand" "=e")
2441 (if_then_else (match_operator 1 "v9_regcmp_op"
2442 [(match_operand:DI 2 "register_operand" "r")
2444 (match_operand:DF 3 "register_operand" "e")
2445 (match_operand:DF 4 "register_operand" "0")))]
2446 "TARGET_V9 && TARGET_FPU"
2447 "fmovrd%D1 %2,%r3,%0"
2448 [(set_attr "type" "cmove")])
2450 (define_insn "*movtf_cc_reg_sp64"
2451 [(set (match_operand:TF 0 "register_operand" "=e")
2452 (if_then_else (match_operator 1 "v9_regcmp_op"
2453 [(match_operand:DI 2 "register_operand" "r")
2455 (match_operand:TF 3 "register_operand" "e")
2456 (match_operand:TF 4 "register_operand" "0")))]
2457 "TARGET_V9 && TARGET_FPU"
2458 "fmovrq%D1 %2,%r3,%0"
2459 [(set_attr "type" "cmove")])
2461 (define_insn "*movsf_ccfp_sp64"
2462 [(set (match_operand:SF 0 "register_operand" "=f")
2463 (if_then_else (match_operator 1 "comparison_operator"
2464 [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
2466 (match_operand:SF 3 "register_operand" "f")
2467 (match_operand:SF 4 "register_operand" "0")))]
2468 "TARGET_V9 && TARGET_FPU"
2470 [(set_attr "type" "cmove")])
2472 (define_insn "*movsf_ccfpe_sp64"
2473 [(set (match_operand:SF 0 "register_operand" "=f")
2474 (if_then_else (match_operator 1 "comparison_operator"
2475 [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
2477 (match_operand:SF 3 "register_operand" "f")
2478 (match_operand:SF 4 "register_operand" "0")))]
2479 "TARGET_V9 && TARGET_FPU"
2481 [(set_attr "type" "cmove")])
2483 (define_insn "*movdf_ccfp_sp64"
2484 [(set (match_operand:DF 0 "register_operand" "=e")
2485 (if_then_else (match_operator 1 "comparison_operator"
2486 [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
2488 (match_operand:DF 3 "register_operand" "e")
2489 (match_operand:DF 4 "register_operand" "0")))]
2490 "TARGET_V9 && TARGET_FPU"
2492 [(set_attr "type" "cmove")])
2494 (define_insn "*movdf_ccfpe_sp64"
2495 [(set (match_operand:DF 0 "register_operand" "=e")
2496 (if_then_else (match_operator 1 "comparison_operator"
2497 [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
2499 (match_operand:DF 3 "register_operand" "e")
2500 (match_operand:DF 4 "register_operand" "0")))]
2501 "TARGET_V9 && TARGET_FPU"
2503 [(set_attr "type" "cmove")])
2505 (define_insn "*movtf_ccfp_sp64"
2506 [(set (match_operand:TF 0 "register_operand" "=e")
2507 (if_then_else (match_operator 1 "comparison_operator"
2508 [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
2510 (match_operand:TF 3 "register_operand" "e")
2511 (match_operand:TF 4 "register_operand" "0")))]
2512 "TARGET_V9 && TARGET_FPU"
2514 [(set_attr "type" "cmove")])
2516 (define_insn "*movtf_ccfpe_sp64"
2517 [(set (match_operand:TF 0 "register_operand" "=e")
2518 (if_then_else (match_operator 1 "comparison_operator"
2519 [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
2521 (match_operand:TF 3 "register_operand" "e")
2522 (match_operand:TF 4 "register_operand" "0")))]
2523 "TARGET_V9 && TARGET_FPU"
2525 [(set_attr "type" "cmove")])
2527 (define_insn "*movsf_cc_sp64"
2528 [(set (match_operand:SF 0 "register_operand" "=f")
2529 (if_then_else (match_operator 1 "comparison_operator"
2530 [(reg:CC 0) (const_int 0)])
2531 (match_operand:SF 2 "register_operand" "f")
2532 (match_operand:SF 3 "register_operand" "0")))]
2533 "TARGET_V9 && TARGET_FPU"
2534 "fmovs%C1 %%icc,%2,%0"
2535 [(set_attr "type" "cmove")])
2537 (define_insn "*movdf_cc_sp64"
2538 [(set (match_operand:DF 0 "register_operand" "=e")
2539 (if_then_else (match_operator 1 "comparison_operator"
2540 [(reg:CC 0) (const_int 0)])
2541 (match_operand:DF 2 "register_operand" "e")
2542 (match_operand:DF 3 "register_operand" "0")))]
2543 "TARGET_V9 && TARGET_FPU"
2544 "fmovd%C1 %%icc,%2,%0"
2545 [(set_attr "type" "cmove")])
2547 (define_insn "*movtf_cc_sp64"
2548 [(set (match_operand:TF 0 "register_operand" "=e")
2549 (if_then_else (match_operator 1 "comparison_operator"
2550 [(reg:CC 0) (const_int 0)])
2551 (match_operand:TF 2 "register_operand" "e")
2552 (match_operand:TF 3 "register_operand" "0")))]
2553 "TARGET_V9 && TARGET_FPU"
2554 "fmovq%C1 %%icc,%2,%0"
2555 [(set_attr "type" "cmove")])
2557 (define_insn "*movsf_ccx_sp64"
2558 [(set (match_operand:SF 0 "register_operand" "=f")
2559 (if_then_else (match_operator 1 "comparison_operator"
2560 [(reg:CCX 0) (const_int 0)])
2561 (match_operand:SF 2 "register_operand" "f")
2562 (match_operand:SF 3 "register_operand" "0")))]
2563 "TARGET_V9 && TARGET_FPU"
2564 "fmovs%C1 %%xcc,%2,%0"
2565 [(set_attr "type" "cmove")])
2567 (define_insn "*movdf_ccx_sp64"
2568 [(set (match_operand:DF 0 "register_operand" "=e")
2569 (if_then_else (match_operator 1 "comparison_operator"
2570 [(reg:CCX 0) (const_int 0)])
2571 (match_operand:DF 2 "register_operand" "e")
2572 (match_operand:DF 3 "register_operand" "0")))]
2573 "TARGET_V9 && TARGET_FPU"
2574 "fmovd%C1 %%xcc,%2,%0"
2575 [(set_attr "type" "cmove")])
2577 (define_insn "*movtf_ccx_sp64"
2578 [(set (match_operand:TF 0 "register_operand" "=e")
2579 (if_then_else (match_operator 1 "comparison_operator"
2580 [(reg:CCX 0) (const_int 0)])
2581 (match_operand:TF 2 "register_operand" "e")
2582 (match_operand:TF 3 "register_operand" "0")))]
2583 "TARGET_V9 && TARGET_FPU"
2584 "fmovq%C1 %%xcc,%2,%0"
2585 [(set_attr "type" "cmove")])
2587 ;;- zero extension instructions
2589 ;; These patterns originally accepted general_operands, however, slightly
2590 ;; better code is generated by only accepting register_operands, and then
2591 ;; letting combine generate the ldu[hb] insns.
2593 (define_expand "zero_extendhisi2"
2594 [(set (match_operand:SI 0 "register_operand" "")
2595 (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
2599 rtx temp = gen_reg_rtx (SImode);
2600 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
2601 int op1_subword = 0;
2603 if (GET_CODE (operand1) == SUBREG)
2605 op1_subword = SUBREG_WORD (operand1);
2606 operand1 = XEXP (operand1, 0);
2609 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2612 emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
2616 (define_insn "*zero_extendhisi2_insn"
2617 [(set (match_operand:SI 0 "register_operand" "=r")
2618 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2621 [(set_attr "type" "load")])
2623 (define_expand "zero_extendqihi2"
2624 [(set (match_operand:HI 0 "register_operand" "")
2625 (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
2629 (define_insn "*zero_extendqihi2_insn"
2630 [(set (match_operand:HI 0 "register_operand" "=r,r")
2631 (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2632 "GET_CODE (operands[1]) != CONST_INT"
2636 [(set_attr "type" "unary,load")
2637 (set_attr "length" "1")])
2639 (define_expand "zero_extendqisi2"
2640 [(set (match_operand:SI 0 "register_operand" "")
2641 (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
2645 (define_insn "*zero_extendqisi2_insn"
2646 [(set (match_operand:SI 0 "register_operand" "=r,r")
2647 (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2648 "GET_CODE (operands[1]) != CONST_INT"
2652 [(set_attr "type" "unary,load")
2653 (set_attr "length" "1")])
2655 (define_expand "zero_extendqidi2"
2656 [(set (match_operand:DI 0 "register_operand" "")
2657 (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
2661 (define_insn "*zero_extendqidi2_insn"
2662 [(set (match_operand:DI 0 "register_operand" "=r,r")
2663 (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2664 "TARGET_V9 && GET_CODE (operands[1]) != CONST_INT"
2668 [(set_attr "type" "unary,load")
2669 (set_attr "length" "1")])
2671 (define_expand "zero_extendhidi2"
2672 [(set (match_operand:DI 0 "register_operand" "")
2673 (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
2677 rtx temp = gen_reg_rtx (DImode);
2678 rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48);
2679 int op1_subword = 0;
2681 if (GET_CODE (operand1) == SUBREG)
2683 op1_subword = SUBREG_WORD (operand1);
2684 operand1 = XEXP (operand1, 0);
2687 emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2690 emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
2694 (define_insn "*zero_extendhidi2_insn"
2695 [(set (match_operand:DI 0 "register_operand" "=r")
2696 (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
2699 [(set_attr "type" "load")])
2701 ;; ??? Write truncdisi pattern using sra?
2703 (define_expand "zero_extendsidi2"
2704 [(set (match_operand:DI 0 "register_operand" "")
2705 (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
2709 (define_insn "*zero_extendsidi2_insn"
2710 [(set (match_operand:DI 0 "register_operand" "=r,r")
2711 (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
2712 "TARGET_V9 && GET_CODE (operands[1]) != CONST_INT"
2716 [(set_attr "type" "unary,load")
2717 (set_attr "length" "1")])
2719 ;; Simplify comparisons of extended values.
2721 (define_insn "*cmp_zero_extendqisi2"
2723 (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
2726 "andcc %0,0xff,%%g0"
2727 [(set_attr "type" "compare")])
2729 (define_insn "*cmp_zero_extendqisi2_set"
2731 (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
2733 (set (match_operand:SI 0 "register_operand" "=r")
2734 (zero_extend:SI (match_dup 1)))]
2737 [(set_attr "type" "unary")])
2739 ;; Similarly, handle SI->QI mode truncation followed by a compare.
2741 (define_insn "*cmp_siqi_trunc"
2743 (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
2746 "andcc %0,0xff,%%g0"
2747 [(set_attr "type" "compare")])
2749 (define_insn "*cmp_siqi_trunc_set"
2751 (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
2753 (set (match_operand:QI 0 "register_operand" "=r")
2757 [(set_attr "type" "unary")])
2759 ;;- sign extension instructions
2761 ;; These patterns originally accepted general_operands, however, slightly
2762 ;; better code is generated by only accepting register_operands, and then
2763 ;; letting combine generate the lds[hb] insns.
2765 (define_expand "extendhisi2"
2766 [(set (match_operand:SI 0 "register_operand" "")
2767 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
2771 rtx temp = gen_reg_rtx (SImode);
2772 rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
2773 int op1_subword = 0;
2775 if (GET_CODE (operand1) == SUBREG)
2777 op1_subword = SUBREG_WORD (operand1);
2778 operand1 = XEXP (operand1, 0);
2781 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2784 emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
2788 (define_insn "*sign_extendhisi2_insn"
2789 [(set (match_operand:SI 0 "register_operand" "=r")
2790 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2793 [(set_attr "type" "load")])
2795 (define_expand "extendqihi2"
2796 [(set (match_operand:HI 0 "register_operand" "")
2797 (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
2801 rtx temp = gen_reg_rtx (SImode);
2802 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
2803 int op1_subword = 0;
2804 int op0_subword = 0;
2806 if (GET_CODE (operand1) == SUBREG)
2808 op1_subword = SUBREG_WORD (operand1);
2809 operand1 = XEXP (operand1, 0);
2811 if (GET_CODE (operand0) == SUBREG)
2813 op0_subword = SUBREG_WORD (operand0);
2814 operand0 = XEXP (operand0, 0);
2816 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2819 if (GET_MODE (operand0) != SImode)
2820 operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword);
2821 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
2825 (define_insn "*sign_extendqihi2_insn"
2826 [(set (match_operand:HI 0 "register_operand" "=r")
2827 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2830 [(set_attr "type" "load")])
2832 (define_expand "extendqisi2"
2833 [(set (match_operand:SI 0 "register_operand" "")
2834 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
2838 rtx temp = gen_reg_rtx (SImode);
2839 rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
2840 int op1_subword = 0;
2842 if (GET_CODE (operand1) == SUBREG)
2844 op1_subword = SUBREG_WORD (operand1);
2845 operand1 = XEXP (operand1, 0);
2848 emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2851 emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
2855 (define_insn "*sign_extendqisi2_insn"
2856 [(set (match_operand:SI 0 "register_operand" "=r")
2857 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2860 [(set_attr "type" "load")])
2862 (define_expand "extendqidi2"
2863 [(set (match_operand:DI 0 "register_operand" "")
2864 (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
2868 rtx temp = gen_reg_rtx (DImode);
2869 rtx shift_56 = gen_rtx (CONST_INT, VOIDmode, 56);
2870 int op1_subword = 0;
2872 if (GET_CODE (operand1) == SUBREG)
2874 op1_subword = SUBREG_WORD (operand1);
2875 operand1 = XEXP (operand1, 0);
2878 emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2881 emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
2885 (define_insn "*sign_extendqidi2_insn"
2886 [(set (match_operand:DI 0 "register_operand" "=r")
2887 (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
2890 [(set_attr "type" "load")])
2892 (define_expand "extendhidi2"
2893 [(set (match_operand:DI 0 "register_operand" "")
2894 (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
2898 rtx temp = gen_reg_rtx (DImode);
2899 rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48);
2900 int op1_subword = 0;
2902 if (GET_CODE (operand1) == SUBREG)
2904 op1_subword = SUBREG_WORD (operand1);
2905 operand1 = XEXP (operand1, 0);
2908 emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2911 emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
2915 (define_insn "*sign_extendhidi2_insn"
2916 [(set (match_operand:DI 0 "register_operand" "=r")
2917 (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
2920 [(set_attr "type" "load")])
2922 (define_expand "extendsidi2"
2923 [(set (match_operand:DI 0 "register_operand" "")
2924 (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
2928 (define_insn "*sign_extendsidi2_insn"
2929 [(set (match_operand:DI 0 "register_operand" "=r,r")
2930 (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
2935 [(set_attr "type" "unary,load")
2936 (set_attr "length" "1")])
2938 ;; Special pattern for optimizing bit-field compares. This is needed
2939 ;; because combine uses this as a canonical form.
2941 (define_insn "*cmp_zero_extract"
2944 (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
2945 (match_operand:SI 1 "small_int" "n")
2946 (match_operand:SI 2 "small_int" "n"))
2948 "INTVAL (operands[2]) > 19"
2951 int len = INTVAL (operands[1]);
2952 int pos = 32 - INTVAL (operands[2]) - len;
2953 unsigned mask = ((1 << len) - 1) << pos;
2955 operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
2956 return \"andcc %0,%1,%%g0\";
2959 (define_insn "*cmp_zero_extract_sp64"
2962 (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
2963 (match_operand:SI 1 "small_int" "n")
2964 (match_operand:SI 2 "small_int" "n"))
2966 "TARGET_V9 && INTVAL (operands[2]) > 51"
2969 int len = INTVAL (operands[1]);
2970 int pos = 64 - INTVAL (operands[2]) - len;
2971 unsigned mask = ((1 << len) - 1) << pos;
2973 operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
2974 return \"andcc %0,%1,%%g0\";
2977 ;; Conversions between float, double and long double.
2979 (define_insn "extendsfdf2"
2980 [(set (match_operand:DF 0 "register_operand" "=e")
2982 (match_operand:SF 1 "register_operand" "f")))]
2985 [(set_attr "type" "fp")])
2987 (define_insn "extendsftf2"
2988 [(set (match_operand:TF 0 "register_operand" "=e")
2990 (match_operand:SF 1 "register_operand" "f")))]
2991 "TARGET_FPU && TARGET_HARD_QUAD"
2993 [(set_attr "type" "fp")])
2995 (define_insn "extenddftf2"
2996 [(set (match_operand:TF 0 "register_operand" "=e")
2998 (match_operand:DF 1 "register_operand" "e")))]
2999 "TARGET_FPU && TARGET_HARD_QUAD"
3001 [(set_attr "type" "fp")])
3003 (define_insn "truncdfsf2"
3004 [(set (match_operand:SF 0 "register_operand" "=f")
3006 (match_operand:DF 1 "register_operand" "e")))]
3009 [(set_attr "type" "fp")])
3011 (define_insn "trunctfsf2"
3012 [(set (match_operand:SF 0 "register_operand" "=f")
3014 (match_operand:TF 1 "register_operand" "e")))]
3015 "TARGET_FPU && TARGET_HARD_QUAD"
3017 [(set_attr "type" "fp")])
3019 (define_insn "trunctfdf2"
3020 [(set (match_operand:DF 0 "register_operand" "=e")
3022 (match_operand:TF 1 "register_operand" "e")))]
3023 "TARGET_FPU && TARGET_HARD_QUAD"
3025 [(set_attr "type" "fp")])
3027 ;; Conversion between fixed point and floating point.
3029 (define_insn "floatsisf2"
3030 [(set (match_operand:SF 0 "register_operand" "=f")
3031 (float:SF (match_operand:SI 1 "register_operand" "f")))]
3034 [(set_attr "type" "fp")])
3036 (define_insn "floatsidf2"
3037 [(set (match_operand:DF 0 "register_operand" "=e")
3038 (float:DF (match_operand:SI 1 "register_operand" "f")))]
3041 [(set_attr "type" "fp")])
3043 (define_insn "floatsitf2"
3044 [(set (match_operand:TF 0 "register_operand" "=e")
3045 (float:TF (match_operand:SI 1 "register_operand" "f")))]
3046 "TARGET_FPU && TARGET_HARD_QUAD"
3048 [(set_attr "type" "fp")])
3050 ;; Now the same for 64 bit sources.
3051 ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2).
3053 (define_expand "floatdisf2"
3054 [(parallel [(set (match_operand:SF 0 "register_operand" "")
3055 (float:SF (match_operand:DI 1 "general_operand" "")))
3056 (clobber (match_dup 2))
3057 (clobber (match_dup 3))])]
3058 "TARGET_V9 && TARGET_FPU"
3061 operands[2] = gen_reg_rtx (DFmode);
3062 operands[3] = sparc64_fpconv_stack_temp ();
3065 (define_expand "floatdidf2"
3066 [(parallel [(set (match_operand:DF 0 "register_operand" "")
3067 (float:DF (match_operand:DI 1 "general_operand" "")))
3068 (clobber (match_dup 2))
3069 (clobber (match_dup 3))])]
3070 "TARGET_V9 && TARGET_FPU"
3073 operands[2] = gen_reg_rtx (DFmode);
3074 operands[3] = sparc64_fpconv_stack_temp ();
3077 (define_expand "floatditf2"
3078 [(parallel [(set (match_operand:TF 0 "register_operand" "")
3079 (float:TF (match_operand:DI 1 "general_operand" "")))
3080 (clobber (match_dup 2))
3081 (clobber (match_dup 3))])]
3082 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3085 operands[2] = gen_reg_rtx (DFmode);
3086 operands[3] = sparc64_fpconv_stack_temp ();
3089 (define_insn "*floatdisf2_insn"
3090 [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
3091 (float:SF (match_operand:DI 1 "general_operand" "rm")))
3092 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3093 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3094 "TARGET_V9 && TARGET_FPU"
3097 if (GET_CODE (operands[1]) == MEM)
3098 output_asm_insn (\"ldd %1,%2\", operands);
3100 output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3101 return \"fxtos %2,%0\";
3103 [(set_attr "type" "fp")
3104 (set_attr "length" "3")])
3106 (define_insn "*floatdidf2_insn"
3107 [(parallel [(set (match_operand:DF 0 "register_operand" "=e")
3108 (float:DF (match_operand:DI 1 "general_operand" "rm")))
3109 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3110 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3111 "TARGET_V9 && TARGET_FPU"
3114 if (GET_CODE (operands[1]) == MEM)
3115 output_asm_insn (\"ldd %1,%2\", operands);
3117 output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3118 return \"fxtod %2,%0\";
3120 [(set_attr "type" "fp")
3121 (set_attr "length" "3")])
3123 (define_insn "*floatditf2_insn"
3124 [(parallel [(set (match_operand:TF 0 "register_operand" "=e")
3125 (float:TF (match_operand:DI 1 "general_operand" "rm")))
3126 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3127 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3128 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3131 if (GET_CODE (operands[1]) == MEM)
3132 output_asm_insn (\"ldd %1,%2\", operands);
3134 output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3135 return \"fxtoq %2,%0\";
3137 [(set_attr "type" "fp")
3138 (set_attr "length" "3")])
3140 ;; ??? Ideally, these are what we would like to use.
3142 (define_insn "floatdisf2_sp64"
3143 [(set (match_operand:SF 0 "register_operand" "=f")
3144 (float:SF (match_operand:DI 1 "register_operand" "e")))]
3145 "0 && TARGET_V9 && TARGET_FPU"
3147 [(set_attr "type" "fp")])
3149 (define_insn "floatdidf2_sp64"
3150 [(set (match_operand:DF 0 "register_operand" "=e")
3151 (float:DF (match_operand:DI 1 "register_operand" "e")))]
3152 "0 && TARGET_V9 && TARGET_FPU"
3154 [(set_attr "type" "fp")])
3156 (define_insn "floatditf2_sp64"
3157 [(set (match_operand:TF 0 "register_operand" "=e")
3158 (float:TF (match_operand:DI 1 "register_operand" "e")))]
3159 "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3161 [(set_attr "type" "fp")])
3163 ;; Convert a float to an actual integer.
3164 ;; Truncation is performed as part of the conversion.
3166 (define_insn "fix_truncsfsi2"
3167 [(set (match_operand:SI 0 "register_operand" "=f")
3168 (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3171 [(set_attr "type" "fp")])
3173 (define_insn "fix_truncdfsi2"
3174 [(set (match_operand:SI 0 "register_operand" "=f")
3175 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3178 [(set_attr "type" "fp")])
3180 (define_insn "fix_trunctfsi2"
3181 [(set (match_operand:SI 0 "register_operand" "=f")
3182 (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3183 "TARGET_FPU && TARGET_HARD_QUAD"
3185 [(set_attr "type" "fp")])
3187 ;; Now the same, for 64-bit targets
3188 ;; ??? We try to work around an interesting problem.
3189 ;; If gcc tries to do a subreg on the result it will get the wrong answer:
3190 ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as
3191 ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change
3192 ;; the "0" to a "1". One could enhance alter_subreg but it is not clear how to
3195 (define_expand "fix_truncsfdi2"
3196 [(parallel [(set (match_operand:DI 0 "general_operand" "")
3197 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
3198 (clobber (match_dup 2))
3199 (clobber (match_dup 3))])]
3200 "TARGET_V9 && TARGET_FPU"
3203 operands[2] = gen_reg_rtx (DFmode);
3204 operands[3] = sparc64_fpconv_stack_temp ();
3207 (define_expand "fix_truncdfdi2"
3208 [(parallel [(set (match_operand:DI 0 "general_operand" "")
3209 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
3210 (clobber (match_dup 2))
3211 (clobber (match_dup 3))])]
3212 "TARGET_V9 && TARGET_FPU"
3215 operands[2] = gen_reg_rtx (DFmode);
3216 operands[3] = sparc64_fpconv_stack_temp ();
3219 (define_expand "fix_trunctfdi2"
3220 [(parallel [(set (match_operand:DI 0 "general_operand" "")
3221 (fix:DI (fix:TF (match_operand:TF 1 "register_operand" ""))))
3222 (clobber (match_dup 2))
3223 (clobber (match_dup 3))])]
3224 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3227 operands[2] = gen_reg_rtx (DFmode);
3228 operands[3] = sparc64_fpconv_stack_temp ();
3231 (define_insn "*fix_truncsfdi2_insn"
3232 [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3233 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
3234 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3235 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3236 "TARGET_V9 && TARGET_FPU"
3239 output_asm_insn (\"fstox %1,%2\", operands);
3240 if (GET_CODE (operands[0]) == MEM)
3241 return \"std %2,%0\";
3243 return \"std %2,%3\;ldx %3,%0\";
3245 [(set_attr "type" "fp")
3246 (set_attr "length" "3")])
3248 (define_insn "*fix_truncdfdi2_insn"
3249 [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3250 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))
3251 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3252 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3253 "TARGET_V9 && TARGET_FPU"
3256 output_asm_insn (\"fdtox %1,%2\", operands);
3257 if (GET_CODE (operands[0]) == MEM)
3258 return \"std %2,%0\";
3260 return \"std %2,%3\;ldx %3,%0\";
3262 [(set_attr "type" "fp")
3263 (set_attr "length" "3")])
3265 (define_insn "*fix_trunctfdi2_insn"
3266 [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3267 (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))
3268 (clobber (match_operand:DF 2 "register_operand" "=&e"))
3269 (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3270 "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3273 output_asm_insn (\"fqtox %1,%2\", operands);
3274 if (GET_CODE (operands[0]) == MEM)
3275 return \"std %2,%0\";
3277 return \"std %2,%3\;ldx %3,%0\";
3279 [(set_attr "type" "fp")
3280 (set_attr "length" "3")])
3282 ;; ??? Ideally, these are what we would like to use.
3284 (define_insn "fix_truncsfdi2_sp64"
3285 [(set (match_operand:DI 0 "register_operand" "=e")
3286 (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3287 "0 && TARGET_V9 && TARGET_FPU"
3289 [(set_attr "type" "fp")])
3291 (define_insn "fix_truncdfdi2_sp64"
3292 [(set (match_operand:DI 0 "register_operand" "=e")
3293 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3294 "0 && TARGET_V9 && TARGET_FPU"
3296 [(set_attr "type" "fp")])
3298 (define_insn "fix_trunctfdi2_sp64"
3299 [(set (match_operand:DI 0 "register_operand" "=e")
3300 (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3301 "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3303 [(set_attr "type" "fp")])
3305 ;;- arithmetic instructions
3307 (define_expand "adddi3"
3308 [(set (match_operand:DI 0 "register_operand" "=r")
3309 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3310 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3316 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3317 gen_rtx (SET, VOIDmode, operands[0],
3318 gen_rtx (PLUS, DImode, operands[1],
3320 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0)))));
3325 (define_insn "*adddi3_sp32"
3326 [(set (match_operand:DI 0 "register_operand" "=r")
3327 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3328 (match_operand:DI 2 "arith_double_operand" "rHI")))
3329 (clobber (reg:SI 0))]
3333 rtx op2 = operands[2];
3335 /* If constant is positive, upper bits zeroed, otherwise unchanged.
3336 Give the assembler a chance to pick the move instruction. */
3337 if (GET_CODE (op2) == CONST_INT)
3339 int sign = INTVAL (op2);
3341 return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
3342 return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
3344 else if (GET_CODE (op2) == CONST_DOUBLE)
3347 xoperands[0] = operands[0];
3348 xoperands[1] = operands[1];
3349 xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
3350 xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
3351 if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1])
3352 output_asm_insn (\"add %1,%3,%0\", xoperands);
3354 output_asm_insn (\"addcc %R1,%2,%R0\;addx %1,%3,%0\", xoperands);
3357 return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
3359 [(set_attr "length" "2")])
3361 (define_insn "*adddi3_sp64"
3362 [(set (match_operand:DI 0 "register_operand" "=r")
3363 (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3364 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3368 (define_insn "addsi3"
3369 [(set (match_operand:SI 0 "register_operand" "=r")
3370 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3371 (match_operand:SI 2 "arith_operand" "rI")))]
3374 [(set_attr "type" "ialu")])
3376 (define_insn "*cmp_cc_plus"
3377 [(set (reg:CC_NOOV 0)
3378 (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
3379 (match_operand:SI 1 "arith_operand" "rI"))
3383 [(set_attr "type" "compare")])
3385 (define_insn "*cmp_ccx_plus"
3386 [(set (reg:CCX_NOOV 0)
3387 (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
3388 (match_operand:DI 1 "arith_double_operand" "rHI"))
3392 [(set_attr "type" "compare")])
3394 (define_insn "*cmp_cc_plus_set"
3395 [(set (reg:CC_NOOV 0)
3396 (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3397 (match_operand:SI 2 "arith_operand" "rI"))
3399 (set (match_operand:SI 0 "register_operand" "=r")
3400 (plus:SI (match_dup 1) (match_dup 2)))]
3404 (define_insn "*cmp_ccx_plus_set"
3405 [(set (reg:CCX_NOOV 0)
3406 (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3407 (match_operand:DI 2 "arith_double_operand" "rHI"))
3409 (set (match_operand:DI 0 "register_operand" "=r")
3410 (plus:DI (match_dup 1) (match_dup 2)))]
3414 (define_expand "subdi3"
3415 [(set (match_operand:DI 0 "register_operand" "=r")
3416 (minus:DI (match_operand:DI 1 "register_operand" "r")
3417 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3423 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3424 gen_rtx (SET, VOIDmode, operands[0],
3425 gen_rtx (MINUS, DImode, operands[1],
3427 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0)))));
3432 (define_insn "*subdi3_sp32"
3433 [(set (match_operand:DI 0 "register_operand" "=r")
3434 (minus:DI (match_operand:DI 1 "register_operand" "r")
3435 (match_operand:DI 2 "arith_double_operand" "rHI")))
3436 (clobber (reg:SI 0))]
3440 rtx op2 = operands[2];
3442 /* If constant is positive, upper bits zeroed, otherwise unchanged.
3443 Give the assembler a chance to pick the move instruction. */
3444 if (GET_CODE (op2) == CONST_INT)
3446 int sign = INTVAL (op2);
3448 return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
3449 return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
3451 else if (GET_CODE (op2) == CONST_DOUBLE)
3454 xoperands[0] = operands[0];
3455 xoperands[1] = operands[1];
3456 xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
3457 xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
3458 if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1])
3459 output_asm_insn (\"sub %1,%3,%0\", xoperands);
3461 output_asm_insn (\"subcc %R1,%2,%R0\;subx %1,%3,%0\", xoperands);
3464 return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
3466 [(set_attr "length" "2")])
3468 (define_insn "*subdi3_sp64"
3469 [(set (match_operand:DI 0 "register_operand" "=r")
3470 (minus:DI (match_operand:DI 1 "register_operand" "r")
3471 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3475 (define_insn "subsi3"
3476 [(set (match_operand:SI 0 "register_operand" "=r")
3477 (minus:SI (match_operand:SI 1 "register_operand" "r")
3478 (match_operand:SI 2 "arith_operand" "rI")))]
3481 [(set_attr "type" "ialu")])
3483 (define_insn "*cmp_minus_cc"
3484 [(set (reg:CC_NOOV 0)
3485 (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
3486 (match_operand:SI 1 "arith_operand" "rI"))
3490 [(set_attr "type" "compare")])
3492 (define_insn "*cmp_minus_ccx"
3493 [(set (reg:CCX_NOOV 0)
3494 (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
3495 (match_operand:DI 1 "arith_double_operand" "rHI"))
3499 [(set_attr "type" "compare")])
3501 (define_insn "*cmp_minus_cc_set"
3502 [(set (reg:CC_NOOV 0)
3503 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
3504 (match_operand:SI 2 "arith_operand" "rI"))
3506 (set (match_operand:SI 0 "register_operand" "=r")
3507 (minus:SI (match_dup 1) (match_dup 2)))]
3511 (define_insn "*cmp_minus_ccx_set"
3512 [(set (reg:CCX_NOOV 0)
3513 (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
3514 (match_operand:DI 2 "arith_double_operand" "rHI"))
3516 (set (match_operand:DI 0 "register_operand" "=r")
3517 (minus:DI (match_dup 1) (match_dup 2)))]
3521 ;; This is anachronistic, and should not be used in v9 software.
3522 ;; The v9 compiler will widen the args and use muldi3.
3524 (define_insn "mulsi3"
3525 [(set (match_operand:SI 0 "register_operand" "=r")
3526 (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3527 (match_operand:SI 2 "arith_operand" "rI")))]
3528 "TARGET_V8 || TARGET_SPARCLITE"
3530 [(set_attr "type" "imul")])
3532 (define_insn "muldi3"
3533 [(set (match_operand:DI 0 "register_operand" "=r")
3534 (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
3535 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3539 ;; It is not known whether this will match.
3541 (define_insn "*cmp_mul_set"
3542 [(set (match_operand:SI 0 "register_operand" "=r")
3543 (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3544 (match_operand:SI 2 "arith_operand" "rI")))
3545 (set (reg:CC_NOOV 0)
3546 (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
3548 "TARGET_V8 || TARGET_SPARCLITE"
3550 [(set_attr "type" "imul")])
3552 (define_expand "mulsidi3"
3553 [(set (match_operand:DI 0 "register_operand" "")
3554 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3555 (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
3556 "TARGET_V8 || TARGET_SPARCLITE"
3559 if (CONSTANT_P (operands[2]))
3561 emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
3566 (define_insn "*mulsidi3_sp32"
3567 [(set (match_operand:DI 0 "register_operand" "=r")
3568 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3569 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3570 "TARGET_V8 || TARGET_SPARCLITE"
3571 "smul %1,%2,%R0\;rd %%y,%0"
3572 [(set_attr "length" "2")])
3574 ;; Extra pattern, because sign_extend of a constant isn't valid.
3576 (define_insn "const_mulsidi3"
3577 [(set (match_operand:DI 0 "register_operand" "=r")
3578 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3579 (match_operand:SI 2 "small_int" "I")))]
3580 "TARGET_V8 || TARGET_SPARCLITE"
3581 "smul %1,%2,%R0\;rd %%y,%0"
3582 [(set_attr "length" "2")])
3584 (define_expand "smulsi3_highpart"
3585 [(set (match_operand:SI 0 "register_operand" "")
3587 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3588 (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
3590 "TARGET_V8 || TARGET_SPARCLITE"
3593 if (CONSTANT_P (operands[2]))
3595 emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
3600 (define_insn "*smulsidi3_highpart_sp32"
3601 [(set (match_operand:SI 0 "register_operand" "=r")
3603 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3604 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
3606 "TARGET_V8 || TARGET_SPARCLITE"
3607 "smul %1,%2,%%g0\;rd %%y,%0"
3608 [(set_attr "length" "2")])
3610 (define_insn "const_smulsi3_highpart"
3611 [(set (match_operand:SI 0 "register_operand" "=r")
3613 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3614 (match_operand:SI 2 "register_operand" "r"))
3616 "TARGET_V8 || TARGET_SPARCLITE"
3617 "smul %1,%2,%%g0\;rd %%y,%0"
3618 [(set_attr "length" "2")])
3620 (define_expand "umulsidi3"
3621 [(set (match_operand:DI 0 "register_operand" "")
3622 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3623 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
3624 "TARGET_V8 || TARGET_SPARCLITE"
3627 if (CONSTANT_P (operands[2]))
3629 emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
3634 (define_insn "*umulsidi3_sp32"
3635 [(set (match_operand:DI 0 "register_operand" "=r")
3636 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3637 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3638 "TARGET_V8 || TARGET_SPARCLITE"
3639 "umul %1,%2,%R0\;rd %%y,%0"
3640 [(set_attr "length" "2")])
3642 ;; Extra pattern, because sign_extend of a constant isn't valid.
3644 (define_insn "const_umulsidi3"
3645 [(set (match_operand:DI 0 "register_operand" "=r")
3646 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3647 (match_operand:SI 2 "uns_small_int" "")))]
3648 "TARGET_V8 || TARGET_SPARCLITE"
3649 "umul %1,%2,%R0\;rd %%y,%0"
3650 [(set_attr "length" "2")])
3652 (define_expand "umulsi3_highpart"
3653 [(set (match_operand:SI 0 "register_operand" "")
3655 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3656 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
3658 "TARGET_V8 || TARGET_SPARCLITE"
3661 if (CONSTANT_P (operands[2]))
3663 emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
3668 (define_insn "*umulsidi3_highpart_sp32"
3669 [(set (match_operand:SI 0 "register_operand" "=r")
3671 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3672 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
3674 "TARGET_V8 || TARGET_SPARCLITE"
3675 "umul %1,%2,%%g0\;rd %%y,%0"
3676 [(set_attr "length" "2")])
3678 (define_insn "const_umulsi3_highpart"
3679 [(set (match_operand:SI 0 "register_operand" "=r")
3681 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3682 (match_operand:SI 2 "uns_small_int" ""))
3684 "TARGET_V8 || TARGET_SPARCLITE"
3685 "umul %1,%2,%%g0\;rd %%y,%0"
3686 [(set_attr "length" "2")])
3688 ;; The architecture specifies that there must be 3 instructions between
3689 ;; a y register write and a use of it for correct results.
3691 (define_insn "divsi3"
3692 [(set (match_operand:SI 0 "register_operand" "=r")
3693 (div:SI (match_operand:SI 1 "register_operand" "r")
3694 (match_operand:SI 2 "arith_operand" "rI")))
3695 (clobber (match_scratch:SI 3 "=&r"))]
3697 "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0"
3698 [(set_attr "length" "6")])
3700 (define_insn "divdi3"
3701 [(set (match_operand:DI 0 "register_operand" "=r")
3702 (div:DI (match_operand:DI 1 "register_operand" "r")
3703 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3707 ;; It is not known whether this will match.
3709 (define_insn "*cmp_sdiv_cc_set"
3710 [(set (match_operand:SI 0 "register_operand" "=r")
3711 (div:SI (match_operand:SI 1 "register_operand" "r")
3712 (match_operand:SI 2 "arith_operand" "rI")))
3714 (compare:CC (div:SI (match_dup 1) (match_dup 2))
3716 (clobber (match_scratch:SI 3 "=&r"))]
3718 "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0"
3719 [(set_attr "length" "6")])
3721 (define_insn "udivsi3"
3722 [(set (match_operand:SI 0 "register_operand" "=r")
3723 (udiv:SI (match_operand:SI 1 "register_operand" "r")
3724 (match_operand:SI 2 "arith_operand" "rI")))]
3726 "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0"
3727 [(set_attr "length" "5")])
3729 (define_insn "udivdi3"
3730 [(set (match_operand:DI 0 "register_operand" "=r")
3731 (udiv:DI (match_operand:DI 1 "register_operand" "r")
3732 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3736 ;; It is not known whether this will match.
3738 (define_insn "*cmp_udiv_cc_set"
3739 [(set (match_operand:SI 0 "register_operand" "=r")
3740 (udiv:SI (match_operand:SI 1 "register_operand" "r")
3741 (match_operand:SI 2 "arith_operand" "rI")))
3743 (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
3746 "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0"
3747 [(set_attr "length" "5")])
3749 ;;- Boolean instructions
3750 ;; We define DImode `and` so with DImode `not` we can get
3751 ;; DImode `andn`. Other combinations are possible.
3753 (define_expand "anddi3"
3754 [(set (match_operand:DI 0 "register_operand" "")
3755 (and:DI (match_operand:DI 1 "arith_double_operand" "")
3756 (match_operand:DI 2 "arith_double_operand" "")))]
3760 (define_insn "*anddi3_sp32"
3761 [(set (match_operand:DI 0 "register_operand" "=r")
3762 (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
3763 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3767 rtx op2 = operands[2];
3769 /* If constant is positive, upper bits zeroed, otherwise unchanged.
3770 Give the assembler a chance to pick the move instruction. */
3771 if (GET_CODE (op2) == CONST_INT)
3773 int sign = INTVAL (op2);
3775 return \"mov %1,%0\;and %R1,%2,%R0\";
3776 return \"mov 0,%0\;and %R1,%2,%R0\";
3778 else if (GET_CODE (op2) == CONST_DOUBLE)
3781 xoperands[0] = operands[0];
3782 xoperands[1] = operands[1];
3783 xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
3784 xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
3785 /* We could optimize then operands[1] == operands[0]
3786 and either half of the constant is -1. */
3787 output_asm_insn (\"and %R1,%2,%R0\;and %1,%3,%0\", xoperands);
3790 return \"and %1,%2,%0\;and %R1,%R2,%R0\";
3792 [(set_attr "length" "2")])
3794 (define_insn "*anddi3_sp64"
3795 [(set (match_operand:DI 0 "register_operand" "=r")
3796 (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
3797 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3801 (define_insn "andsi3"
3802 [(set (match_operand:SI 0 "register_operand" "=r")
3803 (and:SI (match_operand:SI 1 "arith_operand" "%r")
3804 (match_operand:SI 2 "arith_operand" "rI")))]
3807 [(set_attr "type" "ialu")])
3810 [(set (match_operand:SI 0 "register_operand" "")
3811 (and:SI (match_operand:SI 1 "register_operand" "")
3812 (match_operand:SI 2 "" "")))
3813 (clobber (match_operand:SI 3 "register_operand" ""))]
3814 "GET_CODE (operands[2]) == CONST_INT
3815 && !SMALL_INT (operands[2])
3816 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
3817 [(set (match_dup 3) (match_dup 4))
3818 (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
3821 operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
3824 (define_insn "*and_not_di_sp32"
3825 [(set (match_operand:DI 0 "register_operand" "=r")
3826 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
3827 (match_operand:DI 2 "register_operand" "r")))]
3829 "andn %2,%1,%0\;andn %R2,%R1,%R0"
3830 [(set_attr "length" "2")])
3832 (define_insn "*and_not_di_sp64"
3833 [(set (match_operand:DI 0 "register_operand" "=r")
3834 (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
3835 (match_operand:DI 2 "register_operand" "r")))]
3839 (define_insn "*and_not_si"
3840 [(set (match_operand:SI 0 "register_operand" "=r")
3841 (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3842 (match_operand:SI 2 "register_operand" "r")))]
3845 [(set_attr "type" "ialu")])
3847 (define_expand "iordi3"
3848 [(set (match_operand:DI 0 "register_operand" "")
3849 (ior:DI (match_operand:DI 1 "arith_double_operand" "")
3850 (match_operand:DI 2 "arith_double_operand" "")))]
3854 (define_insn "*iordi3_sp32"
3855 [(set (match_operand:DI 0 "register_operand" "=r")
3856 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
3857 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3861 rtx op2 = operands[2];
3863 /* If constant is positive, upper bits zeroed, otherwise unchanged.
3864 Give the assembler a chance to pick the move instruction. */
3865 if (GET_CODE (op2) == CONST_INT)
3867 int sign = INTVAL (op2);
3869 return \"mov -1,%0\;or %R1,%2,%R0\";
3870 return \"mov %1,%0\;or %R1,%2,%R0\";
3872 else if (GET_CODE (op2) == CONST_DOUBLE)
3875 xoperands[0] = operands[0];
3876 xoperands[1] = operands[1];
3877 xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
3878 xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
3879 /* We could optimize then operands[1] == operands[0]
3880 and either half of the constant is 0. */
3881 output_asm_insn (\"or %R1,%2,%R0\;or %1,%3,%0\", xoperands);
3884 return \"or %1,%2,%0\;or %R1,%R2,%R0\";
3886 [(set_attr "length" "2")])
3888 (define_insn "*iordi3_sp64"
3889 [(set (match_operand:DI 0 "register_operand" "=r")
3890 (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
3891 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3895 (define_insn "iorsi3"
3896 [(set (match_operand:SI 0 "register_operand" "=r")
3897 (ior:SI (match_operand:SI 1 "arith_operand" "%r")
3898 (match_operand:SI 2 "arith_operand" "rI")))]
3901 [(set_attr "type" "ialu")])
3904 [(set (match_operand:SI 0 "register_operand" "")
3905 (ior:SI (match_operand:SI 1 "register_operand" "")
3906 (match_operand:SI 2 "" "")))
3907 (clobber (match_operand:SI 3 "register_operand" ""))]
3908 "GET_CODE (operands[2]) == CONST_INT
3909 && !SMALL_INT (operands[2])
3910 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
3911 [(set (match_dup 3) (match_dup 4))
3912 (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
3915 operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
3918 (define_insn "*or_not_di_sp32"
3919 [(set (match_operand:DI 0 "register_operand" "=r")
3920 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
3921 (match_operand:DI 2 "register_operand" "r")))]
3923 "orn %2,%1,%0\;orn %R2,%R1,%R0"
3924 [(set_attr "length" "2")])
3926 (define_insn "*or_not_di_sp64"
3927 [(set (match_operand:DI 0 "register_operand" "=r")
3928 (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
3929 (match_operand:DI 2 "register_operand" "r")))]
3933 (define_insn "*or_not_si"
3934 [(set (match_operand:SI 0 "register_operand" "=r")
3935 (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3936 (match_operand:SI 2 "register_operand" "r")))]
3939 [(set_attr "type" "ialu")])
3941 (define_expand "xordi3"
3942 [(set (match_operand:DI 0 "register_operand" "")
3943 (xor:DI (match_operand:DI 1 "arith_double_operand" "")
3944 (match_operand:DI 2 "arith_double_operand" "")))]
3948 (define_insn "*xorsi3_sp32"
3949 [(set (match_operand:DI 0 "register_operand" "=r")
3950 (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
3951 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3955 rtx op2 = operands[2];
3957 /* If constant is positive, upper bits zeroed, otherwise unchanged.
3958 Give the assembler a chance to pick the move instruction. */
3959 if (GET_CODE (op2) == CONST_INT)
3961 int sign = INTVAL (op2);
3963 return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
3964 return \"mov %1,%0\;xor %R1,%2,%R0\";
3966 else if (GET_CODE (op2) == CONST_DOUBLE)
3969 xoperands[0] = operands[0];
3970 xoperands[1] = operands[1];
3971 xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
3972 xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
3973 /* We could optimize then operands[1] == operands[0]
3974 and either half of the constant is 0. */
3975 output_asm_insn (\"xor %R1,%2,%R0\;xor %1,%3,%0\", xoperands);
3978 return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
3980 [(set_attr "length" "2")])
3982 (define_insn "*xordi3_sp64"
3983 [(set (match_operand:DI 0 "register_operand" "=r")
3984 (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ")
3985 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3989 (define_insn "xorsi3"
3990 [(set (match_operand:SI 0 "register_operand" "=r")
3991 (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
3992 (match_operand:SI 2 "arith_operand" "rI")))]
3995 [(set_attr "type" "ialu")])
3998 [(set (match_operand:SI 0 "register_operand" "")
3999 (xor:SI (match_operand:SI 1 "register_operand" "")
4000 (match_operand:SI 2 "" "")))
4001 (clobber (match_operand:SI 3 "register_operand" ""))]
4002 "GET_CODE (operands[2]) == CONST_INT
4003 && !SMALL_INT (operands[2])
4004 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4005 [(set (match_dup 3) (match_dup 4))
4006 (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
4009 operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
4013 [(set (match_operand:SI 0 "register_operand" "")
4014 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
4015 (match_operand:SI 2 "" ""))))
4016 (clobber (match_operand:SI 3 "register_operand" ""))]
4017 "GET_CODE (operands[2]) == CONST_INT
4018 && !SMALL_INT (operands[2])
4019 && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4020 [(set (match_dup 3) (match_dup 4))
4021 (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
4024 operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
4027 ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
4028 ;; Combine now canonicalizes to the rightmost expression.
4029 (define_insn "*xor_not_di_sp32"
4030 [(set (match_operand:DI 0 "register_operand" "=r")
4031 (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
4032 (match_operand:DI 2 "register_operand" "r"))))]
4034 "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
4035 [(set_attr "length" "2")])
4037 (define_insn "*xor_not_di_sp64"
4038 [(set (match_operand:DI 0 "register_operand" "=r")
4039 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
4040 (match_operand:DI 2 "arith_double_operand" "rHI"))))]
4044 (define_insn "*xor_not_si"
4045 [(set (match_operand:SI 0 "register_operand" "=r")
4046 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4047 (match_operand:SI 2 "arith_operand" "rI"))))]
4050 [(set_attr "type" "ialu")])
4052 ;; These correspond to the above in the case where we also (or only)
4053 ;; want to set the condition code.
4055 (define_insn "*cmp_cc_arith_op"
4058 (match_operator:SI 2 "cc_arithop"
4059 [(match_operand:SI 0 "arith_operand" "%r")
4060 (match_operand:SI 1 "arith_operand" "rI")])
4064 [(set_attr "type" "compare")])
4066 (define_insn "*cmp_ccx_arith_op"
4069 (match_operator:DI 2 "cc_arithop"
4070 [(match_operand:DI 0 "arith_double_operand" "%r")
4071 (match_operand:DI 1 "arith_double_operand" "rHI")])
4075 [(set_attr "type" "compare")])
4077 (define_insn "*cmp_cc_arith_op_set"
4080 (match_operator:SI 3 "cc_arithop"
4081 [(match_operand:SI 1 "arith_operand" "%r")
4082 (match_operand:SI 2 "arith_operand" "rI")])
4084 (set (match_operand:SI 0 "register_operand" "=r")
4089 (define_insn "*cmp_ccx_arith_op_set"
4092 (match_operator:DI 3 "cc_arithop"
4093 [(match_operand:DI 1 "arith_double_operand" "%r")
4094 (match_operand:DI 2 "arith_double_operand" "rHI")])
4096 (set (match_operand:DI 0 "register_operand" "=r")
4101 (define_insn "*cmp_cc_xor_not"
4104 (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
4105 (match_operand:SI 1 "arith_operand" "rI")))
4108 "xnorcc %r0,%1,%%g0"
4109 [(set_attr "type" "compare")])
4111 (define_insn "*cmp_ccx_xor_not"
4114 (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
4115 (match_operand:DI 1 "arith_double_operand" "rHI")))
4118 "xnorcc %r0,%1,%%g0"
4119 [(set_attr "type" "compare")])
4121 (define_insn "*cmp_cc_xor_not_set"
4124 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4125 (match_operand:SI 2 "arith_operand" "rI")))
4127 (set (match_operand:SI 0 "register_operand" "=r")
4128 (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
4132 (define_insn "*cmp_ccx_xor_not_set"
4135 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
4136 (match_operand:DI 2 "arith_double_operand" "rHI")))
4138 (set (match_operand:DI 0 "register_operand" "=r")
4139 (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
4143 (define_insn "*cmp_cc_arith_op_not"
4146 (match_operator:SI 2 "cc_arithopn"
4147 [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
4148 (match_operand:SI 1 "reg_or_0_operand" "rJ")])
4152 [(set_attr "type" "compare")])
4154 (define_insn "*cmp_ccx_arith_op_not"
4157 (match_operator:DI 2 "cc_arithopn"
4158 [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4159 (match_operand:DI 1 "reg_or_0_operand" "rJ")])
4163 [(set_attr "type" "compare")])
4165 (define_insn "*cmp_cc_arith_op_not_set"
4168 (match_operator:SI 3 "cc_arithopn"
4169 [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
4170 (match_operand:SI 2 "reg_or_0_operand" "rJ")])
4172 (set (match_operand:SI 0 "register_operand" "=r")
4177 (define_insn "*cmp_ccx_arith_op_not_set"
4180 (match_operator:DI 3 "cc_arithopn"
4181 [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4182 (match_operand:DI 2 "reg_or_0_operand" "rJ")])
4184 (set (match_operand:DI 0 "register_operand" "=r")
4189 ;; We cannot use the "neg" pseudo insn because the Sun assembler
4190 ;; does not know how to make it work for constants.
4192 (define_expand "negdi2"
4193 [(set (match_operand:DI 0 "register_operand" "=r")
4194 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4200 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
4201 gen_rtx (SET, VOIDmode, operand0,
4202 gen_rtx (NEG, DImode, operand1)),
4203 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 0)))));
4208 (define_insn "*negdi2_sp32"
4209 [(set (match_operand:DI 0 "register_operand" "=r")
4210 (neg:DI (match_operand:DI 1 "register_operand" "r")))
4211 (clobber (reg:SI 0))]
4213 "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
4214 [(set_attr "type" "unary")
4215 (set_attr "length" "2")])
4217 (define_insn "*negdi2_sp64"
4218 [(set (match_operand:DI 0 "register_operand" "=r")
4219 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4222 [(set_attr "type" "unary")
4223 (set_attr "length" "1")])
4225 (define_insn "negsi2"
4226 [(set (match_operand:SI 0 "register_operand" "=r")
4227 (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
4230 [(set_attr "type" "unary")])
4232 (define_insn "*cmp_cc_neg"
4233 [(set (reg:CC_NOOV 0)
4234 (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
4237 "subcc %%g0,%0,%%g0"
4238 [(set_attr "type" "compare")])
4240 (define_insn "*cmp_ccx_neg"
4241 [(set (reg:CCX_NOOV 0)
4242 (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4245 "subcc %%g0,%0,%%g0"
4246 [(set_attr "type" "compare")])
4248 (define_insn "*cmp_cc_set_neg"
4249 [(set (reg:CC_NOOV 0)
4250 (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
4252 (set (match_operand:SI 0 "register_operand" "=r")
4253 (neg:SI (match_dup 1)))]
4256 [(set_attr "type" "unary")])
4258 (define_insn "*cmp_ccx_set_neg"
4259 [(set (reg:CCX_NOOV 0)
4260 (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4262 (set (match_operand:DI 0 "register_operand" "=r")
4263 (neg:DI (match_dup 1)))]
4266 [(set_attr "type" "unary")])
4268 ;; We cannot use the "not" pseudo insn because the Sun assembler
4269 ;; does not know how to make it work for constants.
4270 (define_expand "one_cmpldi2"
4271 [(set (match_operand:DI 0 "register_operand" "")
4272 (not:DI (match_operand:DI 1 "register_operand" "")))]
4276 (define_insn "*one_cmpldi2_sp32"
4277 [(set (match_operand:DI 0 "register_operand" "=r")
4278 (not:DI (match_operand:DI 1 "register_operand" "r")))]
4280 "xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0"
4281 [(set_attr "type" "unary")
4282 (set_attr "length" "2")])
4284 (define_insn "*one_cmpldi2_sp64"
4285 [(set (match_operand:DI 0 "register_operand" "=r")
4286 (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
4289 [(set_attr "type" "unary")])
4291 (define_insn "one_cmplsi2"
4292 [(set (match_operand:SI 0 "register_operand" "=r")
4293 (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
4296 [(set_attr "type" "unary")])
4298 (define_insn "*cmp_cc_not"
4300 (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
4303 "xnorcc %%g0,%0,%%g0"
4304 [(set_attr "type" "compare")])
4306 (define_insn "*cmp_ccx_not"
4308 (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4311 "xnorcc %%g0,%0,%%g0"
4312 [(set_attr "type" "compare")])
4314 (define_insn "*cmp_cc_set_not"
4316 (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
4318 (set (match_operand:SI 0 "register_operand" "=r")
4319 (not:SI (match_dup 1)))]
4322 [(set_attr "type" "unary")])
4324 (define_insn "*cmp_ccx_set_not"
4326 (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4328 (set (match_operand:DI 0 "register_operand" "=r")
4329 (not:DI (match_dup 1)))]
4332 [(set_attr "type" "unary")])
4334 ;; Floating point arithmetic instructions.
4336 (define_insn "addtf3"
4337 [(set (match_operand:TF 0 "register_operand" "=e")
4338 (plus:TF (match_operand:TF 1 "register_operand" "e")
4339 (match_operand:TF 2 "register_operand" "e")))]
4340 "TARGET_FPU && TARGET_HARD_QUAD"
4342 [(set_attr "type" "fp")])
4344 (define_insn "adddf3"
4345 [(set (match_operand:DF 0 "register_operand" "=e")
4346 (plus:DF (match_operand:DF 1 "register_operand" "e")
4347 (match_operand:DF 2 "register_operand" "e")))]
4350 [(set_attr "type" "fp")])
4352 (define_insn "addsf3"
4353 [(set (match_operand:SF 0 "register_operand" "=f")
4354 (plus:SF (match_operand:SF 1 "register_operand" "f")
4355 (match_operand:SF 2 "register_operand" "f")))]
4358 [(set_attr "type" "fp")])
4360 (define_insn "subtf3"
4361 [(set (match_operand:TF 0 "register_operand" "=e")
4362 (minus:TF (match_operand:TF 1 "register_operand" "e")
4363 (match_operand:TF 2 "register_operand" "e")))]
4364 "TARGET_FPU && TARGET_HARD_QUAD"
4366 [(set_attr "type" "fp")])
4368 (define_insn "subdf3"
4369 [(set (match_operand:DF 0 "register_operand" "=e")
4370 (minus:DF (match_operand:DF 1 "register_operand" "e")
4371 (match_operand:DF 2 "register_operand" "e")))]
4374 [(set_attr "type" "fp")])
4376 (define_insn "subsf3"
4377 [(set (match_operand:SF 0 "register_operand" "=f")
4378 (minus:SF (match_operand:SF 1 "register_operand" "f")
4379 (match_operand:SF 2 "register_operand" "f")))]
4382 [(set_attr "type" "fp")])
4384 (define_insn "multf3"
4385 [(set (match_operand:TF 0 "register_operand" "=e")
4386 (mult:TF (match_operand:TF 1 "register_operand" "e")
4387 (match_operand:TF 2 "register_operand" "e")))]
4388 "TARGET_FPU && TARGET_HARD_QUAD"
4390 [(set_attr "type" "fpmul")])
4392 (define_insn "muldf3"
4393 [(set (match_operand:DF 0 "register_operand" "=e")
4394 (mult:DF (match_operand:DF 1 "register_operand" "e")
4395 (match_operand:DF 2 "register_operand" "e")))]
4398 [(set_attr "type" "fpmul")])
4400 (define_insn "mulsf3"
4401 [(set (match_operand:SF 0 "register_operand" "=f")
4402 (mult:SF (match_operand:SF 1 "register_operand" "f")
4403 (match_operand:SF 2 "register_operand" "f")))]
4406 [(set_attr "type" "fpmul")])
4408 (define_insn "*muldf3_extend"
4409 [(set (match_operand:DF 0 "register_operand" "=e")
4410 (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
4411 (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
4412 "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
4414 [(set_attr "type" "fpmul")])
4416 (define_insn "*multf3_extend"
4417 [(set (match_operand:TF 0 "register_operand" "=e")
4418 (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
4419 (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
4420 "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
4422 [(set_attr "type" "fpmul")])
4424 ;; don't have timing for quad-prec. divide.
4425 (define_insn "divtf3"
4426 [(set (match_operand:TF 0 "register_operand" "=e")
4427 (div:TF (match_operand:TF 1 "register_operand" "e")
4428 (match_operand:TF 2 "register_operand" "e")))]
4429 "TARGET_FPU && TARGET_HARD_QUAD"
4431 [(set_attr "type" "fpdivd")])
4433 (define_insn "divdf3"
4434 [(set (match_operand:DF 0 "register_operand" "=e")
4435 (div:DF (match_operand:DF 1 "register_operand" "e")
4436 (match_operand:DF 2 "register_operand" "e")))]
4439 [(set_attr "type" "fpdivd")])
4441 (define_insn "divsf3"
4442 [(set (match_operand:SF 0 "register_operand" "=f")
4443 (div:SF (match_operand:SF 1 "register_operand" "f")
4444 (match_operand:SF 2 "register_operand" "f")))]
4447 [(set_attr "type" "fpdivs")])
4449 (define_insn "negtf2"
4450 [(set (match_operand:TF 0 "register_operand" "=e,e")
4451 (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
4456 return \"fnegd %1,%0\"; /* Can't use fnegs, won't work with upper regs. */
4457 else if (which_alternative == 0)
4458 return \"fnegs %0,%0\";
4460 return \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
4462 [(set_attr "type" "fp")
4463 (set_attr_alternative "length"
4465 (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (const_int 1))])])
4467 (define_insn "negdf2"
4468 [(set (match_operand:DF 0 "register_operand" "=e,e")
4469 (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
4474 return \"fnegd %1,%0\";
4475 else if (which_alternative == 0)
4476 return \"fnegs %0,%0\";
4478 return \"fnegs %1,%0\;fmovs %R1,%R0\";
4480 [(set_attr "type" "fp")
4481 (set_attr_alternative "length"
4483 (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (const_int 1))])])
4485 (define_insn "negsf2"
4486 [(set (match_operand:SF 0 "register_operand" "=f")
4487 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
4490 [(set_attr "type" "fp")])
4492 (define_insn "abstf2"
4493 [(set (match_operand:TF 0 "register_operand" "=e,e")
4494 (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
4499 return \"fabsd %1,%0\"; /* Can't use fabss, won't work with upper regs. */
4500 else if (which_alternative == 0)
4501 return \"fabss %0,%0\";
4503 return \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
4505 [(set_attr "type" "fp")
4506 (set_attr_alternative "length"
4508 (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (const_int 1))])])
4510 (define_insn "absdf2"
4511 [(set (match_operand:DF 0 "register_operand" "=e,e")
4512 (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
4517 return \"fabsd %1,%0\";
4518 else if (which_alternative == 0)
4519 return \"fabss %0,%0\";
4521 return \"fabss %1,%0\;fmovs %R1,%R0\";
4523 [(set_attr "type" "fp")
4524 (set_attr_alternative "length"
4526 (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (const_int 1))])])
4528 (define_insn "abssf2"
4529 [(set (match_operand:SF 0 "register_operand" "=f")
4530 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
4533 [(set_attr "type" "fp")])
4535 (define_insn "sqrttf2"
4536 [(set (match_operand:TF 0 "register_operand" "=e")
4537 (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
4538 "TARGET_FPU && TARGET_HARD_QUAD"
4540 [(set_attr "type" "fpsqrt")])
4542 (define_insn "sqrtdf2"
4543 [(set (match_operand:DF 0 "register_operand" "=e")
4544 (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
4547 [(set_attr "type" "fpsqrt")])
4549 (define_insn "sqrtsf2"
4550 [(set (match_operand:SF 0 "register_operand" "=f")
4551 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
4554 [(set_attr "type" "fpsqrt")])
4556 ;;- arithmetic shift instructions
4558 (define_insn "ashlsi3"
4559 [(set (match_operand:SI 0 "register_operand" "=r")
4560 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4561 (match_operand:SI 2 "arith_operand" "rI")))]
4565 if (GET_CODE (operands[2]) == CONST_INT
4566 && (unsigned) INTVAL (operands[2]) > 31)
4567 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4569 return \"sll %1,%2,%0\";
4571 [(set_attr "type" "shift")])
4573 (define_insn "ashldi3"
4574 [(set (match_operand:DI 0 "register_operand" "=r")
4575 (ashift:DI (match_operand:DI 1 "register_operand" "r")
4576 (match_operand:SI 2 "arith_operand" "rI")))]
4580 if (GET_CODE (operands[2]) == CONST_INT
4581 && (unsigned) INTVAL (operands[2]) > 63)
4582 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4584 return \"sllx %1,%2,%0\";
4587 (define_insn "*cmp_cc_ashift_1"
4588 [(set (reg:CC_NOOV 0)
4589 (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
4594 [(set_attr "type" "compare")])
4596 (define_insn "*cmp_cc_set_ashift_1"
4597 [(set (reg:CC_NOOV 0)
4598 (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
4601 (set (match_operand:SI 0 "register_operand" "=r")
4602 (ashift:SI (match_dup 1) (const_int 1)))]
4606 (define_insn "ashrsi3"
4607 [(set (match_operand:SI 0 "register_operand" "=r")
4608 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
4609 (match_operand:SI 2 "arith_operand" "rI")))]
4613 if (GET_CODE (operands[2]) == CONST_INT
4614 && (unsigned) INTVAL (operands[2]) > 31)
4615 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4617 return \"sra %1,%2,%0\";
4619 [(set_attr "type" "shift")])
4621 (define_insn "ashrdi3"
4622 [(set (match_operand:DI 0 "register_operand" "=r")
4623 (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
4624 (match_operand:SI 2 "arith_operand" "rI")))]
4628 if (GET_CODE (operands[2]) == CONST_INT
4629 && (unsigned) INTVAL (operands[2]) > 63)
4630 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4632 return \"srax %1,%2,%0\";
4635 (define_insn "lshrsi3"
4636 [(set (match_operand:SI 0 "register_operand" "=r")
4637 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
4638 (match_operand:SI 2 "arith_operand" "rI")))]
4642 if (GET_CODE (operands[2]) == CONST_INT
4643 && (unsigned) INTVAL (operands[2]) > 31)
4644 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4646 return \"srl %1,%2,%0\";
4648 [(set_attr "type" "shift")])
4650 (define_insn "lshrdi3"
4651 [(set (match_operand:DI 0 "register_operand" "=r")
4652 (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
4653 (match_operand:SI 2 "arith_operand" "rI")))]
4657 if (GET_CODE (operands[2]) == CONST_INT
4658 && (unsigned) INTVAL (operands[2]) > 63)
4659 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4661 return \"srlx %1,%2,%0\";
4664 ;; Unconditional and other jump instructions
4665 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
4666 ;; following insn is never executed. This saves us a nop. Dbx does not
4667 ;; handle such branches though, so we only use them when optimizing.
4669 [(set (pc) (label_ref (match_operand 0 "" "")))]
4672 [(set_attr "type" "uncond_branch")])
4674 (define_expand "tablejump"
4675 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
4676 (use (label_ref (match_operand 1 "" "")))])]
4680 if (GET_MODE (operands[0]) != Pmode)
4683 /* We need to use the PC value in %o7 that was set up when the address
4684 of the label was loaded into a register, so we need different RTL. */
4688 emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1]));
4690 emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1]));
4695 (define_insn "pic_tablejump_32"
4696 [(set (pc) (match_operand:SI 0 "register_operand" "r"))
4697 (use (label_ref (match_operand 1 "" "")))
4701 [(set_attr "type" "uncond_branch")])
4703 (define_insn "pic_tablejump_64"
4704 [(set (pc) (match_operand:DI 0 "register_operand" "r"))
4705 (use (label_ref (match_operand 1 "" "")))
4709 [(set_attr "type" "uncond_branch")])
4711 (define_insn "*tablejump_sp32"
4712 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
4713 (use (label_ref (match_operand 1 "" "")))]
4716 [(set_attr "type" "uncond_branch")])
4718 (define_insn "*tablejump_sp64"
4719 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
4720 (use (label_ref (match_operand 1 "" "")))]
4723 [(set_attr "type" "uncond_branch")])
4725 (define_insn "*get_pc_sp32"
4726 [(set (pc) (label_ref (match_operand 0 "" "")))
4727 (set (reg:SI 15) (label_ref (match_dup 0)))]
4730 [(set_attr "type" "uncond_branch")])
4732 (define_insn "*get_pc_sp64"
4733 [(set (pc) (label_ref (match_operand 0 "" "")))
4734 (set (reg:DI 15) (label_ref (match_dup 0)))]
4737 [(set_attr "type" "uncond_branch")])
4739 ;; Implement a switch statement for the medium/anywhere code model.
4740 ;; This wouldn't be necessary if we could distinguish label refs of the jump
4741 ;; table from other label refs. The problem is that jump tables live in the
4742 ;; .rodata section and thus we need to add %g4 to get their address.
4744 (define_expand "casesi"
4746 (minus:SI (match_operand:SI 0 "register_operand" "")
4747 (match_operand:SI 1 "nonmemory_operand" "")))
4749 (compare:CC (match_dup 5)
4750 (match_operand:SI 2 "nonmemory_operand" "")))
4752 (if_then_else (gtu (reg:CC 0)
4754 (label_ref (match_operand 4 "" ""))
4756 (parallel [(set (match_dup 6) (high:DI (label_ref (match_operand 3 "" ""))))
4757 (clobber (reg:DI 1))])
4759 (lo_sum:DI (match_dup 6) (label_ref (match_dup 3))))
4760 (set (match_dup 6) (plus:DI (match_dup 6) (reg:DI 4)))
4761 (set (match_dup 7) (zero_extend:DI (match_dup 5)))
4762 (set (match_dup 7) (ashift:DI (match_dup 7) (const_int 3)))
4763 (set (match_dup 7) (mem:DI (plus:DI (match_dup 6) (match_dup 7))))
4764 (set (pc) (match_dup 7))]
4768 operands[5] = gen_reg_rtx (SImode);
4769 operands[6] = gen_reg_rtx (DImode);
4770 operands[7] = gen_reg_rtx (DImode);
4773 ;; This pattern recognizes the "instruction" that appears in
4774 ;; a function call that wants a structure value,
4775 ;; to inform the called function if compiled with Sun CC.
4776 ;(define_insn "*unimp_insn"
4777 ; [(match_operand:SI 0 "immediate_operand" "")]
4778 ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
4780 ; [(set_attr "type" "marker")])
4782 ;;- jump to subroutine
4783 (define_expand "call"
4784 ;; Note that this expression is not used for generating RTL.
4785 ;; All the RTL is generated explicitly below.
4786 [(call (match_operand 0 "call_operand" "")
4787 (match_operand 3 "" "i"))]
4788 ;; operands[2] is next_arg_register
4789 ;; operands[3] is struct_value_size_rtx.
4793 rtx fn_rtx, nregs_rtx;
4795 if (GET_MODE (operands[0]) != FUNCTION_MODE)
4798 if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
4800 /* This is really a PIC sequence. We want to represent
4801 it as a funny jump so it's delay slots can be filled.
4803 ??? But if this really *is* a CALL, will not it clobber the
4804 call-clobbered registers? We lose this if it is a JUMP_INSN.
4805 Why cannot we have delay slots filled if it were a CALL? */
4807 if (! TARGET_V9 && INTVAL (operands[3]) != 0)
4808 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
4809 gen_rtx (SET, VOIDmode, pc_rtx,
4810 XEXP (operands[0], 0)),
4812 gen_rtx (CLOBBER, VOIDmode,
4813 gen_rtx (REG, Pmode, 15)))));
4815 emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
4816 gen_rtx (SET, VOIDmode, pc_rtx,
4817 XEXP (operands[0], 0)),
4818 gen_rtx (CLOBBER, VOIDmode,
4819 gen_rtx (REG, Pmode, 15)))));
4823 fn_rtx = operands[0];
4825 /* Count the number of parameter registers being used by this call.
4826 if that argument is NULL, it means we are using them all, which
4827 means 6 on the sparc. */
4830 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
4832 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
4834 nregs_rtx = const0_rtx;
4837 if (! TARGET_V9 && INTVAL (operands[3]) != 0)
4838 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
4839 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
4841 gen_rtx (CLOBBER, VOIDmode,
4842 gen_rtx (REG, Pmode, 15)))));
4844 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
4845 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
4846 gen_rtx (CLOBBER, VOIDmode,
4847 gen_rtx (REG, Pmode, 15)))));
4851 /* If this call wants a structure value,
4852 emit an unimp insn to let the called function know about this. */
4853 if (! TARGET_V9 && INTVAL (operands[3]) > 0)
4855 rtx insn = emit_insn (operands[3]);
4856 SCHED_GROUP_P (insn) = 1;
4863 ;; We can't use the same pattern for these two insns, because then registers
4864 ;; in the address may not be properly reloaded.
4866 (define_insn "*call_address_sp32"
4867 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
4868 (match_operand 1 "" ""))
4869 (clobber (reg:SI 15))]
4870 ;;- Do not use operand 1 for most machines.
4874 return \"call %a0,%1%#\";
4876 [(set_attr "type" "call")])
4878 (define_insn "*call_symbolic_sp32"
4879 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
4880 (match_operand 1 "" ""))
4881 (clobber (reg:SI 15))]
4882 ;;- Do not use operand 1 for most machines.
4886 return \"call %a0,%1%#\";
4888 [(set_attr "type" "call")])
4890 (define_insn "*call_address_sp64"
4891 [(call (mem:SI (match_operand:DI 0 "address_operand" "p"))
4892 (match_operand 1 "" ""))
4893 (clobber (reg:DI 15))]
4894 ;;- Do not use operand 1 for most machines.
4898 return \"call %a0,%1%#\";
4900 [(set_attr "type" "call")])
4902 (define_insn "*call_symbolic_sp64"
4903 [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s"))
4904 (match_operand 1 "" ""))
4905 (clobber (reg:DI 15))]
4906 ;;- Do not use operand 1 for most machines.
4910 return \"call %a0,%1%#\";
4912 [(set_attr "type" "call")])
4914 ;; This is a call that wants a structure value.
4915 ;; There is no such critter for v9 (??? we may need one anyway).
4916 (define_insn "*call_address_struct_value_sp32"
4917 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
4918 (match_operand 1 "" ""))
4919 (match_operand 2 "immediate_operand" "")
4920 (clobber (reg:SI 15))]
4921 ;;- Do not use operand 1 for most machines.
4922 "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
4925 return \"call %a0,%1\;nop\;unimp %2\";
4927 [(set_attr "type" "call_no_delay_slot")])
4929 ;; This is a call that wants a structure value.
4930 ;; There is no such critter for v9 (??? we may need one anyway).
4931 (define_insn "*call_symbolic_struct_value_sp32"
4932 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
4933 (match_operand 1 "" ""))
4934 (match_operand 2 "immediate_operand" "")
4935 (clobber (reg:SI 15))]
4936 ;;- Do not use operand 1 for most machines.
4937 "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
4940 return \"call %a0,%1\;nop\;unimp %2\";
4942 [(set_attr "type" "call_no_delay_slot")])
4944 ;; This is a call that may want a structure value. This is used for
4946 (define_insn "*call_address_untyped_struct_value_sp32"
4947 [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
4948 (match_operand 1 "" ""))
4949 (match_operand 2 "immediate_operand" "")
4950 (clobber (reg:SI 15))]
4951 ;;- Do not use operand 1 for most machines.
4952 "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
4955 return \"call %a0,%1\;nop\;nop\";
4957 [(set_attr "type" "call_no_delay_slot")])
4959 ;; This is a call that wants a structure value.
4960 (define_insn "*call_symbolic_untyped_struct_value_sp32"
4961 [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
4962 (match_operand 1 "" ""))
4963 (match_operand 2 "immediate_operand" "")
4964 (clobber (reg:SI 15))]
4965 ;;- Do not use operand 1 for most machines.
4966 "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
4969 return \"call %a0,%1\;nop\;nop\";
4971 [(set_attr "type" "call_no_delay_slot")])
4973 (define_expand "call_value"
4974 ;; Note that this expression is not used for generating RTL.
4975 ;; All the RTL is generated explicitly below.
4976 [(set (match_operand 0 "register_operand" "=rf")
4977 (call (match_operand:SI 1 "" "")
4978 (match_operand 4 "" "")))]
4979 ;; operand 2 is stack_size_rtx
4980 ;; operand 3 is next_arg_register
4984 rtx fn_rtx, nregs_rtx;
4987 if (GET_MODE (operands[1]) != FUNCTION_MODE)
4990 fn_rtx = operands[1];
4994 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
4996 nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
4998 nregs_rtx = const0_rtx;
5002 gen_rtx (SET, VOIDmode, operands[0],
5003 gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
5004 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 15)));
5006 emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
5011 (define_insn "*call_value_address_sp32"
5012 [(set (match_operand 0 "" "=rf")
5013 (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
5014 (match_operand 2 "" "")))
5015 (clobber (reg:SI 15))]
5016 ;;- Do not use operand 2 for most machines.
5020 return \"call %a1,%2%#\";
5022 [(set_attr "type" "call")])
5024 (define_insn "*call_value_symbolic_sp32"
5025 [(set (match_operand 0 "" "=rf")
5026 (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
5027 (match_operand 2 "" "")))
5028 (clobber (reg:SI 15))]
5029 ;;- Do not use operand 2 for most machines.
5033 return \"call %a1,%2%#\";
5035 [(set_attr "type" "call")])
5037 (define_insn "*call_value_address_sp64"
5038 [(set (match_operand 0 "" "=rf")
5039 (call (mem:SI (match_operand:DI 1 "address_operand" "p"))
5040 (match_operand 2 "" "")))
5041 (clobber (reg:DI 15))]
5042 ;;- Do not use operand 2 for most machines.
5046 return \"call %a1,%2%#\";
5048 [(set_attr "type" "call")])
5050 (define_insn "*call_value_symbolic_sp64"
5051 [(set (match_operand 0 "" "=rf")
5052 (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s"))
5053 (match_operand 2 "" "")))
5054 (clobber (reg:DI 15))]
5055 ;;- Do not use operand 2 for most machines.
5059 return \"call %a1,%2%#\";
5061 [(set_attr "type" "call")])
5063 (define_expand "untyped_call"
5064 [(parallel [(call (match_operand 0 "" "")
5066 (match_operand 1 "" "")
5067 (match_operand 2 "" "")])]
5073 /* Pass constm1 to indicate that it may expect a structure value, but
5074 we don't know what size it is. */
5075 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
5077 for (i = 0; i < XVECLEN (operands[2], 0); i++)
5079 rtx set = XVECEXP (operands[2], 0, i);
5080 emit_move_insn (SET_DEST (set), SET_SRC (set));
5083 /* The optimizer does not know that the call sets the function value
5084 registers we stored in the result block. We avoid problems by
5085 claiming that all hard registers are used and clobbered at this
5087 emit_insn (gen_blockage ());
5092 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5093 ;; all of memory. This blocks insns from being moved across this point.
5095 (define_insn "blockage"
5096 [(unspec_volatile [(const_int 0)] 0)]
5100 ;; Prepare to return any type including a structure value.
5102 (define_expand "untyped_return"
5103 [(match_operand:BLK 0 "memory_operand" "")
5104 (match_operand 1 "" "")]
5108 rtx valreg1 = gen_rtx (REG, DImode, 24);
5109 rtx valreg2 = gen_rtx (REG, TARGET_V9 ? TFmode : DFmode, 32);
5110 rtx result = operands[0];
5114 rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
5115 rtx value = gen_reg_rtx (SImode);
5117 /* Fetch the instruction where we will return to and see if it's an unimp
5118 instruction (the most significant 10 bits will be zero). If so,
5119 update the return address to skip the unimp instruction. */
5120 emit_move_insn (value,
5121 gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
5122 emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
5123 emit_insn (gen_update_return (rtnreg, value));
5126 /* Reload the function value registers. */
5127 emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
5128 emit_move_insn (valreg2,
5129 change_address (result, TARGET_V9 ? TFmode : DFmode,
5130 plus_constant (XEXP (result, 0), 8)));
5132 /* Put USE insns before the return. */
5133 emit_insn (gen_rtx (USE, VOIDmode, valreg1));
5134 emit_insn (gen_rtx (USE, VOIDmode, valreg2));
5136 /* Construct the return. */
5137 expand_null_return ();
5142 ;; This is a bit of a hack. We're incrementing a fixed register (%i7),
5143 ;; and parts of the compiler don't want to believe that the add is needed.
5145 (define_insn "update_return"
5146 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
5147 (match_operand:SI 1 "register_operand" "r")] 0)]
5149 "cmp %1,0\;be,a .+8\;add %0,4,%0"
5150 [(set_attr "type" "multi")])
5152 (define_insn "return"
5155 "* return output_return (operands);"
5156 [(set_attr "type" "multi")])
5163 (define_expand "indirect_jump"
5164 [(set (pc) (match_operand 0 "address_operand" "p"))]
5168 (define_insn "*branch_sp32"
5169 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
5172 [(set_attr "type" "uncond_branch")])
5174 (define_insn "*branch_sp64"
5175 [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
5178 [(set_attr "type" "uncond_branch")])
5180 ;; ??? Doesn't work with -mflat.
5181 (define_expand "nonlocal_goto"
5182 [(match_operand:SI 0 "general_operand" "")
5183 (match_operand:SI 1 "general_operand" "")
5184 (match_operand:SI 2 "general_operand" "")
5185 (match_operand:SI 3 "" "")]
5189 /* Trap instruction to flush all the register windows. */
5190 emit_insn (gen_flush_register_windows ());
5191 /* Load the fp value for the containing fn into %fp.
5192 This is needed because operands[2] refers to %fp.
5193 Virtual register instantiation fails if the virtual %fp isn't set from a
5194 register. Thus we must copy operands[0] into a register if it isn't
5196 if (GET_CODE (operands[0]) != REG)
5197 operands[0] = force_reg (Pmode, operands[0]);
5198 emit_move_insn (virtual_stack_vars_rtx, operands[0]);
5199 /* Find the containing function's current nonlocal goto handler,
5200 which will do any cleanups and then jump to the label. */
5201 emit_move_insn (gen_rtx (REG, Pmode, 8), operands[1]);
5202 /* Restore %fp from stack pointer value for containing function.
5203 The restore insn that follows will move this to %sp,
5204 and reload the appropriate value into %fp. */
5205 emit_move_insn (frame_pointer_rtx, operands[2]);
5206 /* Put in the static chain register the nonlocal label address. */
5207 emit_move_insn (static_chain_rtx, operands[3]);
5208 /* USE of frame_pointer_rtx added for consistency; not clear if
5210 emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
5211 emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
5212 emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
5213 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, Pmode, 8)));
5214 /* Return, restoring reg window and jumping to goto handler. */
5215 emit_insn (gen_goto_handler_and_restore ());
5219 ;; Special trap insn to flush register windows.
5220 (define_insn "flush_register_windows"
5221 [(unspec_volatile [(const_int 0)] 1)]
5223 "* return TARGET_V9 ? \"flushw\" : \"ta 3\";"
5224 [(set_attr "type" "misc")])
5226 (define_insn "goto_handler_and_restore"
5227 [(unspec_volatile [(const_int 0)] 2)]
5229 "jmp %%o0+0\;restore"
5230 [(set_attr "type" "misc")
5231 (set_attr "length" "2")])
5233 ;; Special pattern for the FLUSH instruction.
5235 (define_insn "flush"
5236 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)]
5238 "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
5239 [(set_attr "type" "misc")])
5243 ;; The scan instruction searches from the most significant bit while ffs
5244 ;; searches from the least significant bit. The bit index and treatment of
5245 ;; zero also differ. It takes at least 7 instructions to get the proper
5246 ;; result. Here is an obvious 8 instruction sequence.
5248 (define_insn "ffssi2"
5249 [(set (match_operand:SI 0 "register_operand" "=&r")
5250 (ffs:SI (match_operand:SI 1 "register_operand" "r")))
5251 (clobber (match_scratch:SI 2 "=&r"))]
5253 "sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0"
5254 [(set_attr "type" "multi")
5255 (set_attr "length" "8")])
5257 ;; ??? This should be a define expand, so that the extra instruction have
5258 ;; a chance of being optimized away.
5260 (define_insn "ffsdi2"
5261 [(set (match_operand:DI 0 "register_operand" "=&r")
5262 (ffs:DI (match_operand:DI 1 "register_operand" "r")))
5263 (clobber (match_scratch:DI 2 "=&r"))]
5265 "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,%%g0,%0"
5266 [(set_attr "type" "multi")
5267 (set_attr "length" "5")])
5269 ;; Split up troublesome insns for better scheduling. */
5271 ;; The following patterns are straightforward. They can be applied
5272 ;; either before or after register allocation.
5275 [(set (match_operand 0 "splittable_symbolic_memory_operand" "")
5276 (match_operand 1 "reg_or_0_operand" ""))
5277 (clobber (match_operand:SI 2 "register_operand" ""))]
5279 [(set (match_dup 2) (high:SI (match_dup 3)))
5280 (set (match_dup 4) (match_dup 1))]
5283 operands[3] = XEXP (operands[0], 0);
5284 operands[4] = gen_rtx (MEM, GET_MODE (operands[0]),
5285 gen_rtx (LO_SUM, SImode, operands[2], operands[3]));
5286 MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]);
5287 MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]);
5288 RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]);
5292 [(set (match_operand 0 "splittable_immediate_memory_operand" "")
5293 (match_operand 1 "general_operand" ""))
5294 (clobber (match_operand:SI 2 "register_operand" ""))]
5296 [(set (match_dup 3) (match_dup 1))]
5299 rtx addr = legitimize_pic_address (XEXP (operands[0], 0),
5300 GET_MODE (operands[0]),
5302 operands[3] = gen_rtx (MEM, GET_MODE (operands[0]), addr);
5303 MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]);
5304 MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]);
5305 RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]);
5309 [(set (match_operand 0 "register_operand" "")
5310 (match_operand 1 "splittable_immediate_memory_operand" ""))]
5312 [(set (match_dup 0) (match_dup 2))]
5315 rtx addr = legitimize_pic_address (XEXP (operands[1], 0),
5316 GET_MODE (operands[1]),
5318 operands[2] = gen_rtx (MEM, GET_MODE (operands[1]), addr);
5319 MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
5320 MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
5321 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
5324 ;; Sign- and Zero-extend operations can have symbolic memory operands.
5327 [(set (match_operand 0 "register_operand" "")
5328 (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))]
5330 [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))]
5333 rtx addr = legitimize_pic_address (XEXP (operands[2], 0),
5334 GET_MODE (operands[2]),
5336 operands[3] = gen_rtx (MEM, GET_MODE (operands[2]), addr);
5337 MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]);
5338 MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]);
5339 RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]);
5343 [(set (match_operand:SI 0 "register_operand" "")
5344 (match_operand:SI 1 "immediate_operand" ""))]
5345 "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5346 || GET_CODE (operands[1]) == CONST
5347 || GET_CODE (operands[1]) == LABEL_REF)"
5348 [(set (match_dup 0) (high:SI (match_dup 1)))
5350 (lo_sum:SI (match_dup 0) (match_dup 1)))]
5353 ;; LABEL_REFs are not modified by `legitimize_pic_address`
5354 ;; so do not recurse infinitely in the PIC case.
5356 [(set (match_operand:SI 0 "register_operand" "")
5357 (match_operand:SI 1 "immediate_operand" ""))]
5358 "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5359 || GET_CODE (operands[1]) == CONST)"
5360 [(set (match_dup 0) (match_dup 1))]
5363 operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]);
5366 ;; These split sne/seq insns. The forms of the resulting insns are
5367 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
5368 ;; Nothing will look at these in detail after splitting has occurred.
5370 ;; ??? v9 DImode versions are missing because addc and subc use %icc.
5373 [(set (match_operand:SI 0 "register_operand" "")
5374 (ne:SI (match_operand:SI 1 "register_operand" "")
5376 (clobber (reg:CC 0))]
5378 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5380 (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
5384 [(set (match_operand:SI 0 "register_operand" "")
5385 (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5387 (clobber (reg:CC 0))]
5389 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5391 (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
5395 [(set (match_operand:SI 0 "register_operand" "")
5396 (eq:SI (match_operand:SI 1 "register_operand" "")
5398 (clobber (reg:CC 0))]
5400 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5402 (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
5406 [(set (match_operand:SI 0 "register_operand" "")
5407 (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5409 (clobber (reg:CC 0))]
5411 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5413 (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
5417 [(set (match_operand:SI 0 "register_operand" "")
5418 (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5420 (match_operand:SI 2 "register_operand" "")))
5421 (clobber (reg:CC 0))]
5423 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5425 (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
5430 [(set (match_operand:SI 0 "register_operand" "")
5431 (minus:SI (match_operand:SI 2 "register_operand" "")
5432 (ne:SI (match_operand:SI 1 "register_operand" "")
5434 (clobber (reg:CC 0))]
5436 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5438 (set (match_dup 0) (minus:SI (match_dup 2)
5439 (ltu:SI (reg:CC 0) (const_int 0))))]
5443 [(set (match_operand:SI 0 "register_operand" "")
5444 (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5446 (match_operand:SI 2 "register_operand" "")))
5447 (clobber (reg:CC 0))]
5449 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5451 (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
5456 [(set (match_operand:SI 0 "register_operand" "")
5457 (minus:SI (match_operand:SI 2 "register_operand" "")
5458 (eq:SI (match_operand:SI 1 "register_operand" "")
5460 (clobber (reg:CC 0))]
5462 [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
5464 (set (match_dup 0) (minus:SI (match_dup 2)
5465 (geu:SI (reg:CC 0) (const_int 0))))]
5468 ;; Peepholes go at the end.
5470 ;; Optimize consecutive loads or stores into ldd and std when possible.
5471 ;; The conditions in which we do this are very restricted and are
5472 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
5475 [(set (match_operand:SI 0 "register_operand" "=rf")
5476 (match_operand:SI 1 "memory_operand" ""))
5477 (set (match_operand:SI 2 "register_operand" "=rf")
5478 (match_operand:SI 3 "memory_operand" ""))]
5480 && registers_ok_for_ldd_peep (operands[0], operands[2])
5481 && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
5482 && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
5486 [(set (match_operand:SI 0 "memory_operand" "")
5487 (match_operand:SI 1 "register_operand" "rf"))
5488 (set (match_operand:SI 2 "memory_operand" "")
5489 (match_operand:SI 3 "register_operand" "rf"))]
5491 && registers_ok_for_ldd_peep (operands[1], operands[3])
5492 && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
5493 && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
5497 [(set (match_operand:SF 0 "register_operand" "=fr")
5498 (match_operand:SF 1 "memory_operand" ""))
5499 (set (match_operand:SF 2 "register_operand" "=fr")
5500 (match_operand:SF 3 "memory_operand" ""))]
5502 && registers_ok_for_ldd_peep (operands[0], operands[2])
5503 && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
5504 && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
5508 [(set (match_operand:SF 0 "memory_operand" "")
5509 (match_operand:SF 1 "register_operand" "fr"))
5510 (set (match_operand:SF 2 "memory_operand" "")
5511 (match_operand:SF 3 "register_operand" "fr"))]
5513 && registers_ok_for_ldd_peep (operands[1], operands[3])
5514 && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
5515 && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
5519 [(set (match_operand:SI 0 "register_operand" "=rf")
5520 (match_operand:SI 1 "memory_operand" ""))
5521 (set (match_operand:SI 2 "register_operand" "=rf")
5522 (match_operand:SI 3 "memory_operand" ""))]
5524 && registers_ok_for_ldd_peep (operands[2], operands[0])
5525 && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
5526 && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
5530 [(set (match_operand:SI 0 "memory_operand" "")
5531 (match_operand:SI 1 "register_operand" "rf"))
5532 (set (match_operand:SI 2 "memory_operand" "")
5533 (match_operand:SI 3 "register_operand" "rf"))]
5535 && registers_ok_for_ldd_peep (operands[3], operands[1])
5536 && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
5537 && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
5541 [(set (match_operand:SF 0 "register_operand" "=fr")
5542 (match_operand:SF 1 "memory_operand" ""))
5543 (set (match_operand:SF 2 "register_operand" "=fr")
5544 (match_operand:SF 3 "memory_operand" ""))]
5546 && registers_ok_for_ldd_peep (operands[2], operands[0])
5547 && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
5548 && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
5552 [(set (match_operand:SF 0 "memory_operand" "")
5553 (match_operand:SF 1 "register_operand" "fr"))
5554 (set (match_operand:SF 2 "memory_operand" "")
5555 (match_operand:SF 3 "register_operand" "fr"))]
5557 && registers_ok_for_ldd_peep (operands[3], operands[1])
5558 && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
5559 && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
5562 ;; Optimize the case of following a reg-reg move with a test
5563 ;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
5564 ;; This can result from a float to fix conversion.
5567 [(set (match_operand:SI 0 "register_operand" "=r")
5568 (match_operand:SI 1 "register_operand" "r"))
5570 (compare:CC (match_operand:SI 2 "register_operand" "r")
5572 "(rtx_equal_p (operands[2], operands[0])
5573 || rtx_equal_p (operands[2], operands[1]))
5574 && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
5578 [(set (match_operand:DI 0 "register_operand" "=r")
5579 (match_operand:DI 1 "register_operand" "r"))
5581 (compare:CCX (match_operand:DI 2 "register_operand" "r")
5584 && (rtx_equal_p (operands[2], operands[0])
5585 || rtx_equal_p (operands[2], operands[1]))
5586 && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
5589 ;; Do {sign,zero}-extended compares somewhat more efficiently.
5590 ;; ??? Is this now the Right Way to do this? Or will SCRATCH
5591 ;; eventually have some impact here?
5594 [(set (match_operand:HI 0 "register_operand" "")
5595 (match_operand:HI 1 "memory_operand" ""))
5596 (set (match_operand:SI 2 "register_operand" "")
5597 (sign_extend:SI (match_dup 0)))
5599 (compare:CC (match_dup 2)
5602 "ldsh %1,%0\;orcc %0,%%g0,%2")
5605 [(set (match_operand:HI 0 "register_operand" "")
5606 (match_operand:HI 1 "memory_operand" ""))
5607 (set (match_operand:DI 2 "register_operand" "")
5608 (sign_extend:DI (match_dup 0)))
5610 (compare:CCX (match_dup 2)
5613 "ldsh %1,%0\;orcc %0,%%g0,%2")
5616 [(set (match_operand:QI 0 "register_operand" "")
5617 (match_operand:QI 1 "memory_operand" ""))
5618 (set (match_operand:SI 2 "register_operand" "")
5619 (sign_extend:SI (match_dup 0)))
5621 (compare:CC (match_dup 2)
5624 "ldsb %1,%0\;orcc %0,%%g0,%2")
5627 [(set (match_operand:QI 0 "register_operand" "")
5628 (match_operand:QI 1 "memory_operand" ""))
5629 (set (match_operand:DI 2 "register_operand" "")
5630 (sign_extend:DI (match_dup 0)))
5632 (compare:CCX (match_dup 2)
5635 "ldsb %1,%0\;orcc %0,%%g0,%2")
5637 ;; Floating-point move peepholes
5638 ;; ??? v9: Do we want similar ones?
5641 [(set (match_operand:SI 0 "register_operand" "=r")
5642 (lo_sum:SI (match_dup 0)
5643 (match_operand:SI 1 "immediate_operand" "i")))
5644 (set (match_operand:DF 2 "register_operand" "=er")
5645 (mem:DF (match_dup 0)))]
5646 "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
5649 /* Go by way of output_move_double in case the register in operand 2
5650 is not properly aligned for ldd. */
5651 operands[1] = gen_rtx (MEM, DFmode,
5652 gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
5653 operands[0] = operands[2];
5654 return output_move_double (operands);
5658 [(set (match_operand:SI 0 "register_operand" "=r")
5659 (lo_sum:SI (match_dup 0)
5660 (match_operand:SI 1 "immediate_operand" "i")))
5661 (set (match_operand:SF 2 "register_operand" "=fr")
5662 (mem:SF (match_dup 0)))]
5663 "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
5664 "ld [%0+%%lo(%a1)],%2")
5666 ;; Return peepholes. First the "normal" ones
5668 ;; ??? There are QImode, HImode, and SImode versions of this pattern.
5669 ;; It might be possible to write one more general pattern instead of three.
5671 (define_insn "*return_qi"
5672 [(set (match_operand:QI 0 "restore_operand" "")
5673 (match_operand:QI 1 "arith_operand" "rI"))
5678 if (! TARGET_V9 && current_function_returns_struct)
5679 return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5681 return \"ret\;restore %%g0,%1,%Y0\";
5683 [(set_attr "type" "multi")])
5685 (define_insn "*return_hi"
5686 [(set (match_operand:HI 0 "restore_operand" "")
5687 (match_operand:HI 1 "arith_operand" "rI"))
5692 if (! TARGET_V9 && current_function_returns_struct)
5693 return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5695 return \"ret\;restore %%g0,%1,%Y0\";
5697 [(set_attr "type" "multi")])
5699 (define_insn "*return_si"
5700 [(set (match_operand:SI 0 "restore_operand" "")
5701 (match_operand:SI 1 "arith_operand" "rI"))
5706 if (! TARGET_V9 && current_function_returns_struct)
5707 return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5709 return \"ret\;restore %%g0,%1,%Y0\";
5711 [(set_attr "type" "multi")])
5713 ;; The following pattern is only generated by delayed-branch scheduling,
5714 ;; when the insn winds up in the epilogue. This can only happen when
5715 ;; ! TARGET_FPU because otherwise fp return values are in %f0.
5716 (define_insn "*return_sf_no_fpu"
5717 [(set (match_operand:SF 0 "restore_operand" "r")
5718 (match_operand:SF 1 "register_operand" "r"))
5720 "! TARGET_FPU && ! TARGET_EPILOGUE"
5723 if (! TARGET_V9 && current_function_returns_struct)
5724 return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5726 return \"ret\;restore %%g0,%1,%Y0\";
5728 [(set_attr "type" "multi")])
5730 (define_insn "*return_addsi"
5731 [(set (match_operand:SI 0 "restore_operand" "")
5732 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
5733 (match_operand:SI 2 "arith_operand" "rI")))
5738 if (! TARGET_V9 && current_function_returns_struct)
5739 return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
5741 return \"ret\;restore %r1,%2,%Y0\";
5743 [(set_attr "type" "multi")])
5745 (define_insn "*return_di"
5746 [(set (match_operand:DI 0 "restore_operand" "")
5747 (match_operand:DI 1 "arith_double_operand" "rHI"))
5749 "TARGET_V9 && ! TARGET_EPILOGUE"
5750 "ret\;restore %%g0,%1,%Y0"
5751 [(set_attr "type" "multi")])
5753 (define_insn "*return_adddi"
5754 [(set (match_operand:DI 0 "restore_operand" "")
5755 (plus:DI (match_operand:DI 1 "arith_operand" "%r")
5756 (match_operand:DI 2 "arith_double_operand" "rHI")))
5758 "TARGET_V9 && ! TARGET_EPILOGUE"
5759 "ret\;restore %r1,%2,%Y0"
5760 [(set_attr "type" "multi")])
5762 ;; Turned off because it should never match (subtracting a constant
5763 ;; is turned into addition) and because it would do the wrong thing
5764 ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
5765 ;;(define_insn "*minus_const"
5766 ;; [(set (match_operand:SI 0 "restore_operand" "")
5767 ;; (minus:SI (match_operand:SI 1 "register_operand" "r")
5768 ;; (match_operand:SI 2 "small_int" "I")))
5770 ;; "! TARGET_EPILOGUE"
5771 ;; "ret\;restore %1,-(%2),%Y0"
5772 ;; [(set_attr "type" "multi")])
5774 ;; The following pattern is only generated by delayed-branch scheduling,
5775 ;; when the insn winds up in the epilogue.
5776 (define_insn "*return_sf"
5778 (match_operand:SF 0 "register_operand" "f"))
5781 "ret\;fmovs %0,%%f0"
5782 [(set_attr "type" "multi")])
5784 ;; Now peepholes to do a call followed by a jump.
5787 [(parallel [(set (match_operand 0 "" "")
5788 (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
5789 (match_operand 2 "" "")))
5790 (clobber (reg:SI 15))])
5791 (set (pc) (label_ref (match_operand 3 "" "")))]
5792 "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
5795 return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
5799 [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
5800 (match_operand 1 "" ""))
5801 (clobber (reg:SI 15))])
5802 (set (pc) (label_ref (match_operand 2 "" "")))]
5803 "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
5806 return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
5810 [(parallel [(set (match_operand 0 "" "")
5811 (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
5812 (match_operand 2 "" "")))
5813 (clobber (reg:DI 15))])
5814 (set (pc) (label_ref (match_operand 3 "" "")))]
5815 "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
5818 return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
5822 [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
5823 (match_operand 1 "" ""))
5824 (clobber (reg:DI 15))])
5825 (set (pc) (label_ref (match_operand 2 "" "")))]
5826 "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
5829 return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
5832 ;; Other miscellaneous peepholes.
5835 [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
5836 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5838 (clobber (reg:CC 0))])
5839 (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]