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