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