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