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