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