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