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