|
|
1.1 root 1: ;;- Machine description for SPARC chip for GNU C compiler
2: ;; Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
3: ;; Contributed by Michael Tiemann ([email protected])
4:
5: ;; This file is part of GNU CC.
6:
7: ;; GNU CC is free software; you can redistribute it and/or modify
8: ;; it under the terms of the GNU General Public License as published by
9: ;; the Free Software Foundation; either version 2, or (at your option)
10: ;; any later version.
11:
12: ;; GNU CC is distributed in the hope that it will be useful,
13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: ;; GNU General Public License for more details.
16:
17: ;; You should have received a copy of the GNU General Public License
18: ;; along with GNU CC; see the file COPYING. If not, write to
19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20:
21:
22: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23:
24: ;; Insn type. Used to default other attribute values.
25:
26: ;; type "unary" insns have one input operand (1) and one output operand (0)
27: ;; type "binary" insns have two input operands (1,2) and one output (0)
28: ;; type "compare" insns have one or two input operands (0,1) and no output
29: ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
30:
31: (define_attr "type"
32: "move,unary,binary,compare,load,store,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 "movsi"
776: [(set (match_operand:SI 0 "general_operand" "")
777: (match_operand:SI 1 "general_operand" ""))]
778: ""
779: "
780: {
781: if (emit_move_sequence (operands, SImode, NULL_RTX))
782: DONE;
783: }")
784:
785: (define_expand "reload_insi"
786: [(set (match_operand:SI 0 "register_operand" "=r")
787: (match_operand:SI 1 "general_operand" ""))
788: (clobber (match_operand:SI 2 "register_operand" "=&r"))]
789: ""
790: "
791: {
792: if (emit_move_sequence (operands, SImode, operands[2]))
793: DONE;
794:
795: /* We don't want the clobber emitted, so handle this ourselves. */
796: emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
797: DONE;
798: }")
799:
800: ;; We must support both 'r' and 'f' registers here, because combine may
801: ;; convert SFmode hard registers to SImode hard registers when simplifying
802: ;; subreg sets.
803:
804: ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
805: ;; problems with register allocation. Reload might try to put an integer
806: ;; in an fp register, or an fp number is an integer register.
807:
808: (define_insn ""
809: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
810: (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
811: "register_operand (operands[0], SImode)
812: || register_operand (operands[1], SImode)
813: || operands[1] == const0_rtx"
814: "@
815: mov %1,%0
816: fmovs %1,%0
817: sethi %%hi(%a1),%0
818: ld %1,%0
819: ld %1,%0
820: st %r1,%0
821: st %r1,%0"
822: [(set_attr "type" "move,fp,move,load,load,store,store")
823: (set_attr "length" "*,*,1,*,*,*,*")])
824:
825: ;; Special pic pattern, for loading the address of a label into a register.
826: ;; It clobbers o7 because the call puts the return address (i.e. pc value)
827: ;; there.
828:
829: (define_insn ""
830: [(set (match_operand:SI 0 "register_operand" "=r")
831: (match_operand:SI 1 "move_pic_label" "i"))
832: (set (reg:SI 15) (pc))]
833: ""
834: "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
835: [(set_attr "type" "multi")
836: (set_attr "length" "4")])
837:
838: (define_insn ""
839: [(set (match_operand:DI 0 "register_operand" "=r")
840: (high:DI (match_operand 1 "" "")))]
841: "check_pic (1)"
842: "*
843: {
844: rtx op0 = operands[0];
845: rtx op1 = operands[1];
846:
847: if (GET_CODE (op1) == CONST_INT)
848: {
849: operands[0] = operand_subword (op0, 1, 0, DImode);
850: output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
851:
852: operands[0] = operand_subword (op0, 0, 0, DImode);
853: if (INTVAL (op1) < 0)
854: return \"mov -1,%0\";
855: else
856: return \"mov 0,%0\";
857: }
858: else if (GET_CODE (op1) == CONST_DOUBLE)
859: {
860: operands[0] = operand_subword (op0, 1, 0, DImode);
861: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
862: output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
863:
864: operands[0] = operand_subword (op0, 0, 0, DImode);
865: operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
866: return singlemove_string (operands);
867: }
868: else
869: abort ();
870: return \"\";
871: }"
872: [(set_attr "type" "move")
873: (set_attr "length" "2")])
874:
875: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
876: ;; confuse them with real addresses.
877: (define_insn ""
878: [(set (match_operand:SI 0 "register_operand" "=r")
879: (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
880: "check_pic (1)"
881: "sethi %%hi(%a1),%0"
882: [(set_attr "type" "move")
883: (set_attr "length" "1")])
884:
885: (define_insn ""
886: [(set (match_operand:SI 0 "register_operand" "=r")
887: (high:SI (match_operand 1 "" "")))]
888: "check_pic (1)"
889: "sethi %%hi(%a1),%0"
890: [(set_attr "type" "move")
891: (set_attr "length" "1")])
892:
893: (define_insn ""
894: [(set (match_operand:HI 0 "register_operand" "=r")
895: (high:HI (match_operand 1 "" "")))]
896: "check_pic (1)"
897: "sethi %%hi(%a1),%0"
898: [(set_attr "type" "move")
899: (set_attr "length" "1")])
900:
901: (define_insn ""
902: [(set (match_operand:DI 0 "register_operand" "=r")
903: (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
904: (match_operand:DI 2 "immediate_operand" "in")))]
905: ""
906: "*
907: {
908: /* Don't output a 64 bit constant, since we can't trust the assembler to
909: handle it correctly. */
910: if (GET_CODE (operands[2]) == CONST_DOUBLE)
911: operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
912: return \"or %R1,%%lo(%a2),%R0\";
913: }"
914: ;; Need to set length for this arith insn because operand2
915: ;; is not an "arith_operand".
916: [(set_attr "length" "1")])
917:
918: ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't
919: ;; confuse them with real addresses.
920: (define_insn ""
921: [(set (match_operand:SI 0 "register_operand" "=r")
922: (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
923: (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
924: ""
925: "or %1,%%lo(%a2),%0"
926: ;; Need to set length for this arith insn because operand2
927: ;; is not an "arith_operand".
928: [(set_attr "length" "1")])
929:
930: (define_insn ""
931: [(set (match_operand:SI 0 "register_operand" "=r")
932: (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
933: (match_operand:SI 2 "immediate_operand" "in")))]
934: ""
935: "or %1,%%lo(%a2),%0"
936: ;; Need to set length for this arith insn because operand2
937: ;; is not an "arith_operand".
938: [(set_attr "length" "1")])
939:
940: (define_insn ""
941: [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
942: (match_operand:SI 1 "reg_or_0_operand" "rJ"))
943: (clobber (match_scratch:SI 2 "=&r"))]
944: ""
945: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
946: [(set_attr "type" "store")
947: (set_attr "length" "2")])
948:
949: (define_expand "movhi"
950: [(set (match_operand:HI 0 "general_operand" "")
951: (match_operand:HI 1 "general_operand" ""))]
952: ""
953: "
954: {
955: if (emit_move_sequence (operands, HImode, NULL_RTX))
956: DONE;
957: }")
958:
959: (define_insn ""
960: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
961: (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
962: "register_operand (operands[0], HImode)
963: || register_operand (operands[1], HImode)
964: || operands[1] == const0_rtx"
965: "@
966: mov %1,%0
967: sethi %%hi(%a1),%0
968: lduh %1,%0
969: sth %r1,%0"
970: [(set_attr "type" "move,move,load,store")
971: (set_attr "length" "*,1,*,1")])
972:
973: (define_insn ""
974: [(set (match_operand:HI 0 "register_operand" "=r")
975: (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
976: (match_operand 2 "immediate_operand" "in")))]
977: ""
978: "or %1,%%lo(%a2),%0"
979: [(set_attr "length" "1")])
980:
981: (define_insn ""
982: [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
983: (match_operand:HI 1 "reg_or_0_operand" "rJ"))
984: (clobber (match_scratch:SI 2 "=&r"))]
985: ""
986: "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
987: [(set_attr "type" "store")
988: (set_attr "length" "2")])
989:
990: (define_expand "movqi"
991: [(set (match_operand:QI 0 "general_operand" "")
992: (match_operand:QI 1 "general_operand" ""))]
993: ""
994: "
995: {
996: if (emit_move_sequence (operands, QImode, NULL_RTX))
997: DONE;
998: }")
999:
1000: (define_insn ""
1001: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1002: (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1003: "register_operand (operands[0], QImode)
1004: || register_operand (operands[1], QImode)
1005: || operands[1] == const0_rtx"
1006: "@
1007: mov %1,%0
1008: sethi %%hi(%a1),%0
1009: ldub %1,%0
1010: stb %r1,%0"
1011: [(set_attr "type" "move,move,load,store")
1012: (set_attr "length" "*,1,*,1")])
1013:
1014: (define_insn ""
1015: [(set (match_operand:QI 0 "register_operand" "=r")
1016: (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1017: (match_operand 2 "immediate_operand" "in")) 0))]
1018: ""
1019: "or %1,%%lo(%a2),%0"
1020: [(set_attr "length" "1")])
1021:
1022: (define_insn ""
1023: [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1024: (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1025: (clobber (match_scratch:SI 2 "=&r"))]
1026: ""
1027: "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1028: [(set_attr "type" "store")
1029: (set_attr "length" "2")])
1030:
1031: ;; ??? We get better code without it. See output_block_move in sparc.c.
1032:
1033: ;; The definition of this insn does not really explain what it does,
1034: ;; but it should suffice
1035: ;; that anything generated as this insn will be recognized as one
1036: ;; and that it will not successfully combine with anything.
1037: ;(define_expand "movstrsi"
1038: ; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
1039: ; (mem:BLK (match_operand:BLK 1 "general_operand" "")))
1040: ; (use (match_operand:SI 2 "nonmemory_operand" ""))
1041: ; (use (match_operand:SI 3 "immediate_operand" ""))
1042: ; (clobber (match_dup 0))
1043: ; (clobber (match_dup 1))
1044: ; (clobber (match_scratch:SI 4 ""))
1045: ; (clobber (reg:SI 0))
1046: ; (clobber (reg:SI 1))])]
1047: ; ""
1048: ; "
1049: ;{
1050: ; /* If the size isn't known, don't emit inline code. output_block_move
1051: ; would output code that's much slower than the library function.
1052: ; Also don't output code for large blocks. */
1053: ; if (GET_CODE (operands[2]) != CONST_INT
1054: ; || GET_CODE (operands[3]) != CONST_INT
1055: ; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
1056: ; FAIL;
1057: ;
1058: ; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
1059: ; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
1060: ; operands[2] = force_not_mem (operands[2]);
1061: ;}")
1062:
1063: ;(define_insn ""
1064: ; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
1065: ; (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
1066: ; (use (match_operand:SI 2 "nonmemory_operand" "rn"))
1067: ; (use (match_operand:SI 3 "immediate_operand" "i"))
1068: ; (clobber (match_dup 0))
1069: ; (clobber (match_dup 1))
1070: ; (clobber (match_scratch:SI 4 "=&r"))
1071: ; (clobber (reg:SI 0))
1072: ; (clobber (reg:SI 1))]
1073: ; ""
1074: ; "* return output_block_move (operands);"
1075: ; [(set_attr "type" "multi")
1076: ; (set_attr "length" "6")])
1077:
1078: ;; Floating point move insns
1079:
1080: ;; This pattern forces (set (reg:TF ...) (const_double ...))
1081: ;; to be reloaded by putting the constant into memory.
1082: ;; It must come before the more general movtf pattern.
1083: (define_insn ""
1084: [(set (match_operand:TF 0 "general_operand" "=?r,f,o")
1085: (match_operand:TF 1 "" "?E,m,G"))]
1086: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1087: "*
1088: {
1089: switch (which_alternative)
1090: {
1091: case 0:
1092: return output_move_quad (operands);
1093: case 1:
1094: return output_fp_move_quad (operands);
1095: case 2:
1096: operands[1] = adj_offsettable_operand (operands[0], 4);
1097: operands[2] = adj_offsettable_operand (operands[0], 8);
1098: operands[3] = adj_offsettable_operand (operands[0], 12);
1099: return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
1100: }
1101: }"
1102: [(set_attr "type" "load,fpload,store")
1103: (set_attr "length" "5,5,5")])
1104:
1105: (define_expand "movtf"
1106: [(set (match_operand:TF 0 "general_operand" "")
1107: (match_operand:TF 1 "general_operand" ""))]
1108: ""
1109: "
1110: {
1111: if (emit_move_sequence (operands, TFmode, NULL_RTX))
1112: DONE;
1113: }")
1114:
1115: (define_insn ""
1116: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r")
1117: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q"))]
1118: "TARGET_FPU
1119: && (register_operand (operands[0], TFmode)
1120: || register_operand (operands[1], TFmode))"
1121: "*
1122: {
1123: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1124: return output_fp_move_quad (operands);
1125: return output_move_quad (operands);
1126: }"
1127: [(set_attr "type" "fp,move,fpstore,store,fpload,load")
1128: (set_attr "length" "4,4,5,5,5,5")])
1129:
1130: ;; Exactly the same as above, except that all `f' cases are deleted.
1131: ;; This is necessary to prevent reload from ever trying to use a `f' reg
1132: ;; when -mno-fpu.
1133:
1134: (define_insn ""
1135: [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
1136: (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
1137: "! TARGET_FPU
1138: && (register_operand (operands[0], TFmode)
1139: || register_operand (operands[1], TFmode))"
1140: "*
1141: {
1142: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1143: return output_fp_move_quad (operands);
1144: return output_move_quad (operands);
1145: }"
1146: [(set_attr "type" "move,store,load")
1147: (set_attr "length" "4,5,5")])
1148:
1149: (define_insn ""
1150: [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
1151: (match_operand:TF 1 "reg_or_0_operand" "rf,G"))
1152: (clobber (match_scratch:SI 2 "=&r,&r"))]
1153: ""
1154: "*
1155: {
1156: output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1157: if (which_alternative == 0)
1158: return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
1159: else
1160: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
1161: }"
1162: [(set_attr "type" "store")
1163: (set_attr "length" "5")])
1164:
1165: ;; This pattern forces (set (reg:DF ...) (const_double ...))
1166: ;; to be reloaded by putting the constant into memory.
1167: ;; It must come before the more general movdf pattern.
1168:
1169: (define_insn ""
1170: [(set (match_operand:DF 0 "general_operand" "=?r,f,o")
1171: (match_operand:DF 1 "" "?E,m,G"))]
1172: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1173: "*
1174: {
1175: switch (which_alternative)
1176: {
1177: case 0:
1178: return output_move_double (operands);
1179: case 1:
1180: return output_fp_move_double (operands);
1181: case 2:
1182: operands[1] = adj_offsettable_operand (operands[0], 4);
1183: return \"st %%g0,%0\;st %%g0,%1\";
1184: }
1185: }"
1186: [(set_attr "type" "load,fpload,store")
1187: (set_attr "length" "3,3,3")])
1188:
1189: (define_expand "movdf"
1190: [(set (match_operand:DF 0 "general_operand" "")
1191: (match_operand:DF 1 "general_operand" ""))]
1192: ""
1193: "
1194: {
1195: if (emit_move_sequence (operands, DFmode, NULL_RTX))
1196: DONE;
1197: }")
1198:
1199: (define_insn ""
1200: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,&r")
1201: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q"))]
1202: "TARGET_FPU
1203: && (register_operand (operands[0], DFmode)
1204: || register_operand (operands[1], DFmode))"
1205: "*
1206: {
1207: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1208: return output_fp_move_double (operands);
1209: return output_move_double (operands);
1210: }"
1211: [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
1212: (set_attr "length" "1,1,2,2,3,3,3,3")])
1213:
1214: ;; Exactly the same as above, except that all `f' cases are deleted.
1215: ;; This is necessary to prevent reload from ever trying to use a `f' reg
1216: ;; when -mno-fpu.
1217:
1218: (define_insn ""
1219: [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
1220: (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
1221: "! TARGET_FPU
1222: && (register_operand (operands[0], DFmode)
1223: || register_operand (operands[1], DFmode))"
1224: "* return output_move_double (operands);"
1225: [(set_attr "type" "store,load,move,store,load")
1226: (set_attr "length" "1,1,2,3,3")])
1227:
1228: (define_split
1229: [(set (match_operand:DF 0 "register_operand" "")
1230: (match_operand:DF 1 "register_operand" ""))]
1231: "reload_completed"
1232: [(set (match_dup 2) (match_dup 3))
1233: (set (match_dup 4) (match_dup 5))]
1234: "
1235: { operands[2] = operand_subword (operands[0], 0, 0, DFmode);
1236: operands[3] = operand_subword (operands[1], 0, 0, DFmode);
1237: operands[4] = operand_subword (operands[0], 1, 0, DFmode);
1238: operands[5] = operand_subword (operands[1], 1, 0, DFmode); }")
1239:
1240: (define_insn ""
1241: [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
1242: (match_operand:DF 1 "reg_or_0_operand" "rf,G"))
1243: (clobber (match_scratch:SI 2 "=&r,&r"))]
1244: ""
1245: "*
1246: {
1247: output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
1248: if (which_alternative == 0)
1249: return \"std %1,[%2+%%lo(%a0)]\";
1250: else
1251: return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
1252: }"
1253: [(set_attr "type" "store")
1254: (set_attr "length" "3")])
1255:
1256: ;; Double-word move insns.
1257:
1258: (define_expand "movdi"
1259: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1260: (match_operand:DI 1 "general_operand" ""))]
1261: ""
1262: "
1263: {
1264: if (emit_move_sequence (operands, DImode, NULL_RTX))
1265: DONE;
1266: }")
1267:
1268: (define_insn ""
1269: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?Q")
1270: (match_operand:DI 1 "general_operand" "r,r,Q,i,f,Q,f"))]
1271: "register_operand (operands[0], DImode)
1272: || register_operand (operands[1], DImode)
1273: || operands[1] == const0_rtx"
1274: "*
1275: {
1276: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1277: return output_fp_move_double (operands);
1278: return output_move_double (operands);
1279: }"
1280: [(set_attr "type" "move,store,load,multi,fp,fpload,fpstore")
1281: (set_attr "length" "2,3,3,3,2,3,3")])
1282:
1283: ;; Floating-point move insns.
1284:
1285: ;; This pattern forces (set (reg:SF ...) (const_double ...))
1286: ;; to be reloaded by putting the constant into memory.
1287: ;; It must come before the more general movsf pattern.
1288: (define_insn ""
1289: [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
1290: (match_operand:SF 1 "" "?E,m,G"))]
1291: "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
1292: "*
1293: {
1294: switch (which_alternative)
1295: {
1296: case 0:
1297: return singlemove_string (operands);
1298: case 1:
1299: return \"ld %1,%0\";
1300: case 2:
1301: return \"st %%g0,%0\";
1302: }
1303: }"
1304: [(set_attr "type" "load,fpload,store")
1305: (set_attr "length" "2,1,1")])
1306:
1307: (define_expand "movsf"
1308: [(set (match_operand:SF 0 "general_operand" "")
1309: (match_operand:SF 1 "general_operand" ""))]
1310: ""
1311: "
1312: {
1313: if (emit_move_sequence (operands, SFmode, NULL_RTX))
1314: DONE;
1315: }")
1316:
1317: (define_insn ""
1318: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
1319: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
1320: "TARGET_FPU
1321: && (register_operand (operands[0], SFmode)
1322: || register_operand (operands[1], SFmode))"
1323: "@
1324: fmovs %1,%0
1325: mov %1,%0
1326: ld %1,%0
1327: ld %1,%0
1328: st %r1,%0
1329: st %r1,%0"
1330: [(set_attr "type" "fp,move,fpload,load,fpstore,store")])
1331:
1332: ;; Exactly the same as above, except that all `f' cases are deleted.
1333: ;; This is necessary to prevent reload from ever trying to use a `f' reg
1334: ;; when -mno-fpu.
1335:
1336: (define_insn ""
1337: [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
1338: (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
1339: "! TARGET_FPU
1340: && (register_operand (operands[0], SFmode)
1341: || register_operand (operands[1], SFmode))"
1342: "@
1343: mov %1,%0
1344: ld %1,%0
1345: st %r1,%0"
1346: [(set_attr "type" "move,load,store")])
1347:
1348: (define_insn ""
1349: [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
1350: (match_operand:SF 1 "reg_or_0_operand" "rfG"))
1351: (clobber (match_scratch:SI 2 "=&r"))]
1352: ""
1353: "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
1354: [(set_attr "type" "store")
1355: (set_attr "length" "2")])
1356:
1357: ;;- zero extension instructions
1358:
1359: ;; These patterns originally accepted general_operands, however, slightly
1360: ;; better code is generated by only accepting register_operands, and then
1361: ;; letting combine generate the ldu[hb] insns.
1362:
1363: (define_expand "zero_extendhisi2"
1364: [(set (match_operand:SI 0 "register_operand" "")
1365: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
1366: ""
1367: "
1368: {
1369: rtx temp = gen_reg_rtx (SImode);
1370: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1371:
1372: if (GET_CODE (operand1) == SUBREG)
1373: operand1 = XEXP (operand1, 0);
1374:
1375: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1376: shift_16));
1377: emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
1378: DONE;
1379: }")
1380:
1381: (define_insn ""
1382: [(set (match_operand:SI 0 "register_operand" "=r")
1383: (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1384: ""
1385: "lduh %1,%0"
1386: [(set_attr "type" "load")])
1387:
1388: (define_expand "zero_extendqihi2"
1389: [(set (match_operand:HI 0 "register_operand" "")
1390: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1391: ""
1392: "")
1393:
1394: (define_insn ""
1395: [(set (match_operand:HI 0 "register_operand" "=r,r")
1396: (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
1397: "GET_CODE (operands[1]) != CONST_INT"
1398: "@
1399: and %1,0xff,%0
1400: ldub %1,%0"
1401: [(set_attr "type" "unary,load")
1402: (set_attr "length" "1")])
1403:
1404: (define_expand "zero_extendqisi2"
1405: [(set (match_operand:SI 0 "register_operand" "")
1406: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1407: ""
1408: "")
1409:
1410: (define_insn ""
1411: [(set (match_operand:SI 0 "register_operand" "=r,r")
1412: (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
1413: "GET_CODE (operands[1]) != CONST_INT"
1414: "@
1415: and %1,0xff,%0
1416: ldub %1,%0"
1417: [(set_attr "type" "unary,load")
1418: (set_attr "length" "1")])
1419:
1420: (define_insn ""
1421: [(set (reg:CC 0)
1422: (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
1423: (const_int 0)))]
1424: ""
1425: "andcc %0,0xff,%%g0"
1426: [(set_attr "type" "compare")])
1427:
1428: (define_insn ""
1429: [(set (reg:CC 0)
1430: (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
1431: (const_int 0)))
1432: (set (match_operand:SI 0 "register_operand" "=r")
1433: (zero_extend:SI (match_dup 1)))]
1434: ""
1435: "andcc %1,0xff,%0"
1436: [(set_attr "type" "unary")])
1437:
1438: ;; Similarly, handle SI->QI mode truncation followed by a compare.
1439:
1440: (define_insn ""
1441: [(set (reg:CC 0)
1442: (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
1443: (const_int 0)))]
1444: ""
1445: "andcc %0,0xff,%%g0"
1446: [(set_attr "type" "compare")])
1447:
1448: (define_insn ""
1449: [(set (reg:CC 0)
1450: (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
1451: (const_int 0)))
1452: (set (match_operand:QI 0 "register_operand" "=r")
1453: (match_dup 1))]
1454: ""
1455: "andcc %1,0xff,%0"
1456: [(set_attr "type" "unary")])
1457:
1458: ;;- sign extension instructions
1459:
1460: ;; These patterns originally accepted general_operands, however, slightly
1461: ;; better code is generated by only accepting register_operands, and then
1462: ;; letting combine generate the lds[hb] insns.
1463:
1464: (define_expand "extendhisi2"
1465: [(set (match_operand:SI 0 "register_operand" "")
1466: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1467: ""
1468: "
1469: {
1470: rtx temp = gen_reg_rtx (SImode);
1471: rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
1472:
1473: if (GET_CODE (operand1) == SUBREG)
1474: operand1 = XEXP (operand1, 0);
1475:
1476: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1477: shift_16));
1478: emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
1479: DONE;
1480: }")
1481:
1482: (define_insn ""
1483: [(set (match_operand:SI 0 "register_operand" "=r")
1484: (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1485: ""
1486: "ldsh %1,%0"
1487: [(set_attr "type" "load")])
1488:
1489: (define_expand "extendqihi2"
1490: [(set (match_operand:HI 0 "register_operand" "")
1491: (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
1492: ""
1493: "
1494: {
1495: rtx temp = gen_reg_rtx (SImode);
1496: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1497:
1498: if (GET_CODE (operand1) == SUBREG)
1499: operand1 = XEXP (operand1, 0);
1500: if (GET_CODE (operand0) == SUBREG)
1501: operand0 = XEXP (operand0, 0);
1502: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1503: shift_24));
1504: if (GET_MODE (operand0) != SImode)
1505: operand0 = gen_rtx (SUBREG, SImode, operand0, 0);
1506: emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1507: DONE;
1508: }")
1509:
1510: (define_insn ""
1511: [(set (match_operand:HI 0 "register_operand" "=r")
1512: (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
1513: ""
1514: "ldsb %1,%0"
1515: [(set_attr "type" "load")])
1516:
1517: (define_expand "extendqisi2"
1518: [(set (match_operand:SI 0 "register_operand" "")
1519: (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
1520: ""
1521: "
1522: {
1523: rtx temp = gen_reg_rtx (SImode);
1524: rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
1525:
1526: if (GET_CODE (operand1) == SUBREG)
1527: operand1 = XEXP (operand1, 0);
1528: emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0),
1529: shift_24));
1530: emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
1531: DONE;
1532: }")
1533:
1534: (define_insn ""
1535: [(set (match_operand:SI 0 "register_operand" "=r")
1536: (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1537: ""
1538: "ldsb %1,%0"
1539: [(set_attr "type" "load")])
1540:
1541: ;; Special pattern for optimizing bit-field compares. This is needed
1542: ;; because combine uses this as a canonical form.
1543:
1544: (define_insn ""
1545: [(set (reg:CC 0)
1546: (compare:CC
1547: (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
1548: (match_operand:SI 1 "small_int" "n")
1549: (match_operand:SI 2 "small_int" "n"))
1550: (const_int 0)))]
1551: "INTVAL (operands[2]) > 19"
1552: "*
1553: {
1554: int len = INTVAL (operands[1]);
1555: int pos = 32 - INTVAL (operands[2]) - len;
1556: unsigned mask = ((1 << len) - 1) << pos;
1557:
1558: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
1559: return \"andcc %0,%1,%%g0\";
1560: }")
1561:
1562: ;; Conversions between float, double and long double.
1563:
1564: (define_insn "extendsfdf2"
1565: [(set (match_operand:DF 0 "register_operand" "=f")
1566: (float_extend:DF
1567: (match_operand:SF 1 "register_operand" "f")))]
1568: "TARGET_FPU"
1569: "fstod %1,%0"
1570: [(set_attr "type" "fp")])
1571:
1572: (define_insn "extendsftf2"
1573: [(set (match_operand:TF 0 "register_operand" "=f")
1574: (float_extend:TF
1575: (match_operand:SF 1 "register_operand" "f")))]
1576: "TARGET_FPU"
1577: "fstoq %1,%0"
1578: [(set_attr "type" "fp")])
1579:
1580: (define_insn "extenddftf2"
1581: [(set (match_operand:TF 0 "register_operand" "=f")
1582: (float_extend:TF
1583: (match_operand:DF 1 "register_operand" "f")))]
1584: "TARGET_FPU"
1585: "fdtoq %1,%0"
1586: [(set_attr "type" "fp")])
1587:
1588: (define_insn "truncdfsf2"
1589: [(set (match_operand:SF 0 "register_operand" "=f")
1590: (float_truncate:SF
1591: (match_operand:DF 1 "register_operand" "f")))]
1592: "TARGET_FPU"
1593: "fdtos %1,%0"
1594: [(set_attr "type" "fp")])
1595:
1596: (define_insn "trunctfsf2"
1597: [(set (match_operand:SF 0 "register_operand" "=f")
1598: (float_truncate:SF
1599: (match_operand:TF 1 "register_operand" "f")))]
1600: "TARGET_FPU"
1601: "fqtos %1,%0"
1602: [(set_attr "type" "fp")])
1603:
1604: (define_insn "trunctfdf2"
1605: [(set (match_operand:DF 0 "register_operand" "=f")
1606: (float_truncate:DF
1607: (match_operand:TF 1 "register_operand" "f")))]
1608: "TARGET_FPU"
1609: "fqtod %1,%0"
1610: [(set_attr "type" "fp")])
1611:
1612: ;; Conversion between fixed point and floating point.
1613:
1614: (define_insn "floatsisf2"
1615: [(set (match_operand:SF 0 "register_operand" "=f")
1616: (float:SF (match_operand:SI 1 "register_operand" "f")))]
1617: "TARGET_FPU"
1618: "fitos %1,%0"
1619: [(set_attr "type" "fp")])
1620:
1621: (define_insn "floatsidf2"
1622: [(set (match_operand:DF 0 "register_operand" "=f")
1623: (float:DF (match_operand:SI 1 "register_operand" "f")))]
1624: "TARGET_FPU"
1625: "fitod %1,%0"
1626: [(set_attr "type" "fp")])
1627:
1628: (define_insn "floatsitf2"
1629: [(set (match_operand:TF 0 "register_operand" "=f")
1630: (float:TF (match_operand:SI 1 "register_operand" "f")))]
1631: "TARGET_FPU"
1632: "fitoq %1,%0"
1633: [(set_attr "type" "fp")])
1634:
1635: ;; Convert a float to an actual integer.
1636: ;; Truncation is performed as part of the conversion.
1637:
1638: (define_insn "fix_truncsfsi2"
1639: [(set (match_operand:SI 0 "register_operand" "=f")
1640: (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
1641: "TARGET_FPU"
1642: "fstoi %1,%0"
1643: [(set_attr "type" "fp")])
1644:
1645: (define_insn "fix_truncdfsi2"
1646: [(set (match_operand:SI 0 "register_operand" "=f")
1647: (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
1648: "TARGET_FPU"
1649: "fdtoi %1,%0"
1650: [(set_attr "type" "fp")])
1651:
1652: (define_insn "fix_trunctfsi2"
1653: [(set (match_operand:SI 0 "register_operand" "=f")
1654: (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))]
1655: "TARGET_FPU"
1656: "fqtoi %1,%0"
1657: [(set_attr "type" "fp")])
1658:
1659: ;;- arithmetic instructions
1660:
1661: (define_insn "adddi3"
1662: [(set (match_operand:DI 0 "register_operand" "=r")
1663: (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
1664: (match_operand:DI 2 "arith_double_operand" "rHI")))
1665: (clobber (reg:SI 0))]
1666: ""
1667: "*
1668: {
1669: rtx op2 = operands[2];
1670:
1671: /* If constant is positive, upper bits zeroed, otherwise unchanged.
1672: Give the assembler a chance to pick the move instruction. */
1673: if (GET_CODE (op2) == CONST_INT)
1674: {
1675: int sign = INTVAL (op2);
1676: if (sign < 0)
1677: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1678: return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1679: }
1680: else if (GET_CODE (op2) == CONST_DOUBLE)
1681: {
1682: int sign = CONST_DOUBLE_HIGH (op2);
1683: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1684: CONST_DOUBLE_LOW (operands[1]));
1685: if (sign < 0)
1686: return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
1687: return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
1688: }
1689: return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
1690: }"
1691: [(set_attr "length" "2")])
1692:
1693: (define_insn "addsi3"
1694: [(set (match_operand:SI 0 "register_operand" "=r")
1695: (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1696: (match_operand:SI 2 "arith_operand" "rI")))]
1697: ""
1698: "add %1,%2,%0")
1699:
1700: (define_insn ""
1701: [(set (reg:CC_NOOV 0)
1702: (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
1703: (match_operand:SI 1 "arith_operand" "rI"))
1704: (const_int 0)))]
1705: ""
1706: "addcc %0,%1,%%g0"
1707: [(set_attr "type" "compare")])
1708:
1709: (define_insn ""
1710: [(set (reg:CC_NOOV 0)
1711: (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1712: (match_operand:SI 2 "arith_operand" "rI"))
1713: (const_int 0)))
1714: (set (match_operand:SI 0 "register_operand" "=r")
1715: (plus:SI (match_dup 1) (match_dup 2)))]
1716: ""
1717: "addcc %1,%2,%0")
1718:
1719: (define_insn "subdi3"
1720: [(set (match_operand:DI 0 "register_operand" "=r")
1721: (minus:DI (match_operand:DI 1 "register_operand" "r")
1722: (match_operand:DI 2 "arith_double_operand" "rHI")))
1723: (clobber (reg:SI 0))]
1724: ""
1725: "*
1726: {
1727: rtx op2 = operands[2];
1728:
1729: /* If constant is positive, upper bits zeroed, otherwise unchanged.
1730: Give the assembler a chance to pick the move instruction. */
1731: if (GET_CODE (op2) == CONST_INT)
1732: {
1733: int sign = INTVAL (op2);
1734: if (sign < 0)
1735: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1736: return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1737: }
1738: else if (GET_CODE (op2) == CONST_DOUBLE)
1739: {
1740: int sign = CONST_DOUBLE_HIGH (op2);
1741: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1742: CONST_DOUBLE_LOW (operands[1]));
1743: if (sign < 0)
1744: return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
1745: return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
1746: }
1747: return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
1748: }"
1749: [(set_attr "length" "2")])
1750:
1751: (define_insn "subsi3"
1752: [(set (match_operand:SI 0 "register_operand" "=r")
1753: (minus:SI (match_operand:SI 1 "register_operand" "r")
1754: (match_operand:SI 2 "arith_operand" "rI")))]
1755: ""
1756: "sub %1,%2,%0")
1757:
1758: (define_insn ""
1759: [(set (reg:CC_NOOV 0)
1760: (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
1761: (match_operand:SI 1 "arith_operand" "rI"))
1762: (const_int 0)))]
1763: ""
1764: "subcc %0,%1,%%g0"
1765: [(set_attr "type" "compare")])
1766:
1767: (define_insn ""
1768: [(set (reg:CC_NOOV 0)
1769: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
1770: (match_operand:SI 2 "arith_operand" "rI"))
1771: (const_int 0)))
1772: (set (match_operand:SI 0 "register_operand" "=r")
1773: (minus:SI (match_dup 1) (match_dup 2)))]
1774: ""
1775: "subcc %1,%2,%0")
1776:
1777: (define_insn "mulsi3"
1778: [(set (match_operand:SI 0 "register_operand" "=r")
1779: (mult:SI (match_operand:SI 1 "arith_operand" "%r")
1780: (match_operand:SI 2 "arith_operand" "rI")))]
1781: "TARGET_V8 || TARGET_SPARCLITE"
1782: "smul %1,%2,%0")
1783:
1784: ;; It is not known whether this will match.
1785:
1786: (define_insn ""
1787: [(set (match_operand:SI 0 "register_operand" "=r")
1788: (mult:SI (match_operand:SI 1 "arith_operand" "%r")
1789: (match_operand:SI 2 "arith_operand" "rI")))
1790: (set (reg:CC_NOOV 0)
1791: (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
1792: (const_int 0)))]
1793: "TARGET_V8 || TARGET_SPARCLITE"
1794: "smulcc %1,%2,%0")
1795:
1796: (define_expand "mulsidi3"
1797: [(set (match_operand:DI 0 "register_operand" "")
1798: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1799: (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
1800: "TARGET_V8 || TARGET_SPARCLITE"
1801: "
1802: {
1803: if (CONSTANT_P (operands[2]))
1804: {
1805: emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
1806: DONE;
1807: }
1808: }")
1809:
1810: (define_insn ""
1811: [(set (match_operand:DI 0 "register_operand" "=r")
1812: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1813: (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1814: "TARGET_V8 || TARGET_SPARCLITE"
1815: "smul %1,%2,%R0\;rd %%y,%0"
1816: [(set_attr "length" "2")])
1817:
1818: ;; Extra pattern, because sign_extend of a constant isn't legal.
1819:
1820: (define_insn "const_mulsidi3"
1821: [(set (match_operand:DI 0 "register_operand" "=r")
1822: (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1823: (match_operand:SI 2 "small_int" "I")))]
1824: "TARGET_V8 || TARGET_SPARCLITE"
1825: "smul %1,%2,%R0\;rd %%y,%0"
1826: [(set_attr "length" "2")])
1827:
1828: (define_expand "umulsidi3"
1829: [(set (match_operand:DI 0 "register_operand" "")
1830: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1831: (zero_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
1832: "TARGET_V8 || TARGET_SPARCLITE"
1833: "
1834: {
1835: if (CONSTANT_P (operands[2]))
1836: {
1837: emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
1838: DONE;
1839: }
1840: }")
1841:
1842: (define_insn ""
1843: [(set (match_operand:DI 0 "register_operand" "=r")
1844: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1845: (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1846: "TARGET_V8 || TARGET_SPARCLITE"
1847: "umul %1,%2,%R0\;rd %%y,%0"
1848: [(set_attr "length" "2")])
1849:
1850: ;; Extra pattern, because sign_extend of a constant isn't legal.
1851:
1852: (define_insn "const_umulsidi3"
1853: [(set (match_operand:DI 0 "register_operand" "=r")
1854: (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1855: (match_operand:SI 2 "small_int" "I")))]
1856: "TARGET_V8 || TARGET_SPARCLITE"
1857: "umul %1,%2,%R0\;rd %%y,%0"
1858: [(set_attr "length" "2")])
1859:
1860: ;; The architecture specifies that there must be 3 instructions between
1861: ;; a y register write and a use of it for correct results.
1862:
1863: (define_insn "divsi3"
1864: [(set (match_operand:SI 0 "register_operand" "=r")
1865: (div:SI (match_operand:SI 1 "register_operand" "r")
1866: (match_operand:SI 2 "arith_operand" "rI")))
1867: (clobber (match_scratch:SI 3 "=&r"))]
1868: "TARGET_V8"
1869: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0"
1870: [(set_attr "length" "6")])
1871:
1872: ;; It is not known whether this will match.
1873:
1874: (define_insn ""
1875: [(set (match_operand:SI 0 "register_operand" "=r")
1876: (div:SI (match_operand:SI 1 "register_operand" "r")
1877: (match_operand:SI 2 "arith_operand" "rI")))
1878: (set (reg:CC 0)
1879: (compare:CC (div:SI (match_dup 1) (match_dup 2))
1880: (const_int 0)))
1881: (clobber (match_scratch:SI 3 "=&r"))]
1882: "TARGET_V8"
1883: "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0"
1884: [(set_attr "length" "6")])
1885:
1886: (define_insn "udivsi3"
1887: [(set (match_operand:SI 0 "register_operand" "=r")
1888: (udiv:SI (match_operand:SI 1 "register_operand" "r")
1889: (match_operand:SI 2 "arith_operand" "rI")))]
1890: "TARGET_V8"
1891: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0"
1892: [(set_attr "length" "5")])
1893:
1894: ;; It is not known whether this will match.
1895:
1896: (define_insn ""
1897: [(set (match_operand:SI 0 "register_operand" "=r")
1898: (udiv:SI (match_operand:SI 1 "register_operand" "r")
1899: (match_operand:SI 2 "arith_operand" "rI")))
1900: (set (reg:CC 0)
1901: (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
1902: (const_int 0)))]
1903: "TARGET_V8"
1904: "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0"
1905: [(set_attr "length" "5")])
1906:
1907: ;;- and instructions
1908: ;; We define DImode `and` so with DImode `not` we can get
1909: ;; DImode `andn`. Other combinations are possible.
1910:
1911: (define_expand "anddi3"
1912: [(set (match_operand:DI 0 "register_operand" "")
1913: (and:DI (match_operand:DI 1 "arith_double_operand" "")
1914: (match_operand:DI 2 "arith_double_operand" "")))]
1915: ""
1916: "")
1917:
1918: (define_insn ""
1919: [(set (match_operand:DI 0 "register_operand" "=r")
1920: (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
1921: (match_operand:DI 2 "arith_double_operand" "rHI")))]
1922: ""
1923: "*
1924: {
1925: rtx op2 = operands[2];
1926:
1927: /* If constant is positive, upper bits zeroed, otherwise unchanged.
1928: Give the assembler a chance to pick the move instruction. */
1929: if (GET_CODE (op2) == CONST_INT)
1930: {
1931: int sign = INTVAL (op2);
1932: if (sign < 0)
1933: return \"mov %1,%0\;and %R1,%2,%R0\";
1934: return \"mov 0,%0\;and %R1,%2,%R0\";
1935: }
1936: else if (GET_CODE (op2) == CONST_DOUBLE)
1937: {
1938: int sign = CONST_DOUBLE_HIGH (op2);
1939: operands[2] = gen_rtx (CONST_INT, VOIDmode,
1940: CONST_DOUBLE_LOW (operands[1]));
1941: if (sign < 0)
1942: return \"mov %1,%0\;and %R1,%2,%R0\";
1943: return \"mov 0,%0\;and %R1,%2,%R0\";
1944: }
1945: return \"and %1,%2,%0\;and %R1,%R2,%R0\";
1946: }"
1947: [(set_attr "length" "2")])
1948:
1949: (define_insn "andsi3"
1950: [(set (match_operand:SI 0 "register_operand" "=r")
1951: (and:SI (match_operand:SI 1 "arith_operand" "%r")
1952: (match_operand:SI 2 "arith_operand" "rI")))]
1953: ""
1954: "and %1,%2,%0")
1955:
1956: (define_split
1957: [(set (match_operand:SI 0 "register_operand" "")
1958: (and:SI (match_operand:SI 1 "register_operand" "")
1959: (match_operand:SI 2 "" "")))
1960: (clobber (match_operand:SI 3 "register_operand" ""))]
1961: "GET_CODE (operands[2]) == CONST_INT
1962: && !SMALL_INT (operands[2])
1963: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
1964: [(set (match_dup 3) (match_dup 4))
1965: (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
1966: "
1967: {
1968: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
1969: }")
1970:
1971: (define_insn ""
1972: [(set (match_operand:DI 0 "register_operand" "=r")
1973: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
1974: (match_operand:DI 2 "register_operand" "r")))]
1975: ""
1976: "andn %2,%1,%0\;andn %R2,%R1,%R0"
1977: [(set_attr "length" "2")])
1978:
1979: (define_insn ""
1980: [(set (match_operand:SI 0 "register_operand" "=r")
1981: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
1982: (match_operand:SI 2 "register_operand" "r")))]
1983: ""
1984: "andn %2,%1,%0")
1985:
1986: (define_expand "iordi3"
1987: [(set (match_operand:DI 0 "register_operand" "")
1988: (ior:DI (match_operand:DI 1 "arith_double_operand" "")
1989: (match_operand:DI 2 "arith_double_operand" "")))]
1990: ""
1991: "")
1992:
1993: (define_insn ""
1994: [(set (match_operand:DI 0 "register_operand" "=r")
1995: (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
1996: (match_operand:DI 2 "arith_double_operand" "rHI")))]
1997: ""
1998: "*
1999: {
2000: rtx op2 = operands[2];
2001:
2002: /* If constant is positive, upper bits zeroed, otherwise unchanged.
2003: Give the assembler a chance to pick the move instruction. */
2004: if (GET_CODE (op2) == CONST_INT)
2005: {
2006: int sign = INTVAL (op2);
2007: if (sign < 0)
2008: return \"mov -1,%0\;or %R1,%2,%R0\";
2009: return \"mov %1,%0\;or %R1,%2,%R0\";
2010: }
2011: else if (GET_CODE (op2) == CONST_DOUBLE)
2012: {
2013: int sign = CONST_DOUBLE_HIGH (op2);
2014: operands[2] = gen_rtx (CONST_INT, VOIDmode,
2015: CONST_DOUBLE_LOW (operands[1]));
2016: if (sign < 0)
2017: return \"mov -1,%0\;or %R1,%2,%R0\";
2018: return \"mov %1,%0\;or %R1,%2,%R0\";
2019: }
2020: return \"or %1,%2,%0\;or %R1,%R2,%R0\";
2021: }"
2022: [(set_attr "length" "2")])
2023:
2024: (define_insn "iorsi3"
2025: [(set (match_operand:SI 0 "register_operand" "=r")
2026: (ior:SI (match_operand:SI 1 "arith_operand" "%r")
2027: (match_operand:SI 2 "arith_operand" "rI")))]
2028: ""
2029: "or %1,%2,%0")
2030:
2031: (define_split
2032: [(set (match_operand:SI 0 "register_operand" "")
2033: (ior:SI (match_operand:SI 1 "register_operand" "")
2034: (match_operand:SI 2 "" "")))
2035: (clobber (match_operand:SI 3 "register_operand" ""))]
2036: "GET_CODE (operands[2]) == CONST_INT
2037: && !SMALL_INT (operands[2])
2038: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2039: [(set (match_dup 3) (match_dup 4))
2040: (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
2041: "
2042: {
2043: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2044: }")
2045:
2046: (define_insn ""
2047: [(set (match_operand:DI 0 "register_operand" "=r")
2048: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
2049: (match_operand:DI 2 "register_operand" "r")))]
2050: ""
2051: "orn %2,%1,%0\;orn %R2,%R1,%R0"
2052: [(set_attr "length" "2")])
2053:
2054: (define_insn ""
2055: [(set (match_operand:SI 0 "register_operand" "=r")
2056: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
2057: (match_operand:SI 2 "register_operand" "r")))]
2058: ""
2059: "orn %2,%1,%0")
2060:
2061: (define_expand "xordi3"
2062: [(set (match_operand:DI 0 "register_operand" "")
2063: (xor:DI (match_operand:DI 1 "arith_double_operand" "")
2064: (match_operand:DI 2 "arith_double_operand" "")))]
2065: ""
2066: "")
2067:
2068: (define_insn ""
2069: [(set (match_operand:DI 0 "register_operand" "=r")
2070: (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
2071: (match_operand:DI 2 "arith_double_operand" "rHI")))]
2072: ""
2073: "*
2074: {
2075: rtx op2 = operands[2];
2076:
2077: /* If constant is positive, upper bits zeroed, otherwise unchanged.
2078: Give the assembler a chance to pick the move instruction. */
2079: if (GET_CODE (op2) == CONST_INT)
2080: {
2081: int sign = INTVAL (op2);
2082: if (sign < 0)
2083: return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
2084: return \"mov %1,%0\;xor %R1,%2,%R0\";
2085: }
2086: else if (GET_CODE (op2) == CONST_DOUBLE)
2087: {
2088: int sign = CONST_DOUBLE_HIGH (op2);
2089: operands[2] = gen_rtx (CONST_INT, VOIDmode,
2090: CONST_DOUBLE_LOW (operands[1]));
2091: if (sign < 0)
2092: return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
2093: return \"mov %1,%0\;xor %R1,%2,%R0\";
2094: }
2095: return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
2096: }"
2097: [(set_attr "length" "2")])
2098:
2099: (define_insn "xorsi3"
2100: [(set (match_operand:SI 0 "register_operand" "=r")
2101: (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
2102: (match_operand:SI 2 "arith_operand" "rI")))]
2103: ""
2104: "xor %r1,%2,%0")
2105:
2106: (define_split
2107: [(set (match_operand:SI 0 "register_operand" "")
2108: (xor:SI (match_operand:SI 1 "register_operand" "")
2109: (match_operand:SI 2 "" "")))
2110: (clobber (match_operand:SI 3 "register_operand" ""))]
2111: "GET_CODE (operands[2]) == CONST_INT
2112: && !SMALL_INT (operands[2])
2113: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2114: [(set (match_dup 3) (match_dup 4))
2115: (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
2116: "
2117: {
2118: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2119: }")
2120:
2121: (define_split
2122: [(set (match_operand:SI 0 "register_operand" "")
2123: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
2124: (match_operand:SI 2 "" ""))))
2125: (clobber (match_operand:SI 3 "register_operand" ""))]
2126: "GET_CODE (operands[2]) == CONST_INT
2127: && !SMALL_INT (operands[2])
2128: && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
2129: [(set (match_dup 3) (match_dup 4))
2130: (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
2131: "
2132: {
2133: operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
2134: }")
2135:
2136: ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
2137: ;; Combine now canonicalizes to the rightmost expression.
2138: (define_insn ""
2139: [(set (match_operand:DI 0 "register_operand" "=r")
2140: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
2141: (match_operand:DI 2 "register_operand" "r"))))]
2142: ""
2143: "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
2144: [(set_attr "length" "2")])
2145:
2146: (define_insn ""
2147: [(set (match_operand:SI 0 "register_operand" "=r")
2148: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
2149: (match_operand:SI 2 "arith_operand" "rI"))))]
2150: ""
2151: "xnor %r1,%2,%0")
2152:
2153: ;; These correspond to the above in the case where we also (or only)
2154: ;; want to set the condition code.
2155:
2156: (define_insn ""
2157: [(set (reg:CC 0)
2158: (compare:CC
2159: (match_operator:SI 2 "cc_arithop"
2160: [(match_operand:SI 0 "arith_operand" "%r")
2161: (match_operand:SI 1 "arith_operand" "rI")])
2162: (const_int 0)))]
2163: ""
2164: "%A2cc %0,%1,%%g0"
2165: [(set_attr "type" "compare")])
2166:
2167: (define_insn ""
2168: [(set (reg:CC 0)
2169: (compare:CC
2170: (match_operator:SI 3 "cc_arithop"
2171: [(match_operand:SI 1 "arith_operand" "%r")
2172: (match_operand:SI 2 "arith_operand" "rI")])
2173: (const_int 0)))
2174: (set (match_operand:SI 0 "register_operand" "=r")
2175: (match_dup 3))]
2176: ""
2177: "%A3cc %1,%2,%0")
2178:
2179: (define_insn ""
2180: [(set (reg:CC 0)
2181: (compare:CC
2182: (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
2183: (match_operand:SI 1 "arith_operand" "rI")))
2184: (const_int 0)))]
2185: ""
2186: "xnorcc %r0,%1,%%g0"
2187: [(set_attr "type" "compare")])
2188:
2189: (define_insn ""
2190: [(set (reg:CC 0)
2191: (compare:CC
2192: (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
2193: (match_operand:SI 2 "arith_operand" "rI")))
2194: (const_int 0)))
2195: (set (match_operand:SI 0 "register_operand" "=r")
2196: (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
2197: ""
2198: "xnorcc %r1,%2,%0")
2199:
2200: (define_insn ""
2201: [(set (reg:CC 0)
2202: (compare:CC
2203: (match_operator:SI 2 "cc_arithopn"
2204: [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
2205: (match_operand:SI 1 "reg_or_0_operand" "rJ")])
2206: (const_int 0)))]
2207: ""
2208: "%B2cc %r1,%0,%%g0"
2209: [(set_attr "type" "compare")])
2210:
2211: (define_insn ""
2212: [(set (reg:CC 0)
2213: (compare:CC
2214: (match_operator:SI 3 "cc_arithopn"
2215: [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
2216: (match_operand:SI 2 "reg_or_0_operand" "rJ")])
2217: (const_int 0)))
2218: (set (match_operand:SI 0 "register_operand" "=r")
2219: (match_dup 3))]
2220: ""
2221: "%B3cc %r2,%1,%0")
2222:
2223: ;; We cannot use the "neg" pseudo insn because the Sun assembler
2224: ;; does not know how to make it work for constants.
2225:
2226: (define_insn "negdi2"
2227: [(set (match_operand:DI 0 "register_operand" "=r")
2228: (neg:DI (match_operand:DI 1 "register_operand" "r")))
2229: (clobber (reg:SI 0))]
2230: ""
2231: "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
2232: [(set_attr "type" "unary")
2233: (set_attr "length" "2")])
2234:
2235: (define_insn "negsi2"
2236: [(set (match_operand:SI 0 "general_operand" "=r")
2237: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
2238: ""
2239: "sub %%g0,%1,%0"
2240: [(set_attr "type" "unary")])
2241:
2242: (define_insn ""
2243: [(set (reg:CC_NOOV 0)
2244: (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
2245: (const_int 0)))]
2246: ""
2247: "subcc %%g0,%0,%%g0"
2248: [(set_attr "type" "compare")])
2249:
2250: (define_insn ""
2251: [(set (reg:CC_NOOV 0)
2252: (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
2253: (const_int 0)))
2254: (set (match_operand:SI 0 "register_operand" "=r")
2255: (neg:SI (match_dup 1)))]
2256: ""
2257: "subcc %%g0,%1,%0"
2258: [(set_attr "type" "unary")])
2259:
2260: ;; We cannot use the "not" pseudo insn because the Sun assembler
2261: ;; does not know how to make it work for constants.
2262: (define_expand "one_cmpldi2"
2263: [(set (match_operand:DI 0 "register_operand" "=r")
2264: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
2265: ""
2266: "")
2267:
2268: (define_insn ""
2269: [(set (match_operand:DI 0 "register_operand" "=r")
2270: (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
2271: ""
2272: "*
2273: {
2274: rtx op1 = operands[1];
2275:
2276: if (GET_CODE (op1) == CONST_INT)
2277: {
2278: int sign = INTVAL (op1);
2279: if (sign < 0)
2280: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
2281: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
2282: }
2283: else if (GET_CODE (op1) == CONST_DOUBLE)
2284: {
2285: int sign = CONST_DOUBLE_HIGH (op1);
2286: operands[1] = gen_rtx (CONST_INT, VOIDmode,
2287: CONST_DOUBLE_LOW (operands[1]));
2288: if (sign < 0)
2289: return \"xnor %%g0,%1,%R0\;xnor %%g0,-1,%0\";
2290: return \"xnor %%g0,%1,%R0\;xnor %%g0,0,%0\";
2291: }
2292: return \"xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0\";
2293: }"
2294: [(set_attr "type" "unary")
2295: (set_attr "length" "2")])
2296:
2297: (define_insn "one_cmplsi2"
2298: [(set (match_operand:SI 0 "register_operand" "=r")
2299: (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
2300: ""
2301: "xnor %%g0,%1,%0"
2302: [(set_attr "type" "unary")])
2303:
2304: (define_insn ""
2305: [(set (reg:CC 0)
2306: (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
2307: (const_int 0)))]
2308: ""
2309: "xnorcc %%g0,%0,%%g0"
2310: [(set_attr "type" "compare")])
2311:
2312: (define_insn ""
2313: [(set (reg:CC 0)
2314: (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
2315: (const_int 0)))
2316: (set (match_operand:SI 0 "register_operand" "=r")
2317: (not:SI (match_dup 1)))]
2318: ""
2319: "xnorcc %%g0,%1,%0"
2320: [(set_attr "type" "unary")])
2321:
2322: ;; Floating point arithmetic instructions.
2323:
2324: (define_insn "addtf3"
2325: [(set (match_operand:TF 0 "register_operand" "=f")
2326: (plus:TF (match_operand:TF 1 "register_operand" "f")
2327: (match_operand:TF 2 "register_operand" "f")))]
2328: "TARGET_FPU"
2329: "faddq %1,%2,%0"
2330: [(set_attr "type" "fp")])
2331:
2332: (define_insn "adddf3"
2333: [(set (match_operand:DF 0 "register_operand" "=f")
2334: (plus:DF (match_operand:DF 1 "register_operand" "f")
2335: (match_operand:DF 2 "register_operand" "f")))]
2336: "TARGET_FPU"
2337: "faddd %1,%2,%0"
2338: [(set_attr "type" "fp")])
2339:
2340: (define_insn "addsf3"
2341: [(set (match_operand:SF 0 "register_operand" "=f")
2342: (plus:SF (match_operand:SF 1 "register_operand" "f")
2343: (match_operand:SF 2 "register_operand" "f")))]
2344: "TARGET_FPU"
2345: "fadds %1,%2,%0"
2346: [(set_attr "type" "fp")])
2347:
2348: (define_insn "subtf3"
2349: [(set (match_operand:TF 0 "register_operand" "=f")
2350: (minus:TF (match_operand:TF 1 "register_operand" "f")
2351: (match_operand:TF 2 "register_operand" "f")))]
2352: "TARGET_FPU"
2353: "fsubq %1,%2,%0"
2354: [(set_attr "type" "fp")])
2355:
2356: (define_insn "subdf3"
2357: [(set (match_operand:DF 0 "register_operand" "=f")
2358: (minus:DF (match_operand:DF 1 "register_operand" "f")
2359: (match_operand:DF 2 "register_operand" "f")))]
2360: "TARGET_FPU"
2361: "fsubd %1,%2,%0"
2362: [(set_attr "type" "fp")])
2363:
2364: (define_insn "subsf3"
2365: [(set (match_operand:SF 0 "register_operand" "=f")
2366: (minus:SF (match_operand:SF 1 "register_operand" "f")
2367: (match_operand:SF 2 "register_operand" "f")))]
2368: "TARGET_FPU"
2369: "fsubs %1,%2,%0"
2370: [(set_attr "type" "fp")])
2371:
2372: (define_insn "multf3"
2373: [(set (match_operand:TF 0 "register_operand" "=f")
2374: (mult:TF (match_operand:TF 1 "register_operand" "f")
2375: (match_operand:TF 2 "register_operand" "f")))]
2376: "TARGET_FPU"
2377: "fmulq %1,%2,%0"
2378: [(set_attr "type" "fpmul")])
2379:
2380: (define_insn "muldf3"
2381: [(set (match_operand:DF 0 "register_operand" "=f")
2382: (mult:DF (match_operand:DF 1 "register_operand" "f")
2383: (match_operand:DF 2 "register_operand" "f")))]
2384: "TARGET_FPU"
2385: "fmuld %1,%2,%0"
2386: [(set_attr "type" "fpmul")])
2387:
2388: (define_insn "mulsf3"
2389: [(set (match_operand:SF 0 "register_operand" "=f")
2390: (mult:SF (match_operand:SF 1 "register_operand" "f")
2391: (match_operand:SF 2 "register_operand" "f")))]
2392: "TARGET_FPU"
2393: "fmuls %1,%2,%0"
2394: [(set_attr "type" "fpmul")])
2395:
2396: (define_insn ""
2397: [(set (match_operand:DF 0 "register_operand" "=f")
2398: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
2399: (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
2400: "TARGET_V8 && TARGET_FPU"
2401: "fsmuld %1,%2,%0"
2402: [(set_attr "type" "fpmul")])
2403:
2404: (define_insn ""
2405: [(set (match_operand:TF 0 "register_operand" "=f")
2406: (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "f"))
2407: (float_extend:TF (match_operand:DF 2 "register_operand" "f"))))]
2408: "TARGET_V8 && TARGET_FPU"
2409: "fdmulq %1,%2,%0"
2410: [(set_attr "type" "fpmul")])
2411:
2412: (define_insn "divtf3"
2413: [(set (match_operand:TF 0 "register_operand" "=f")
2414: (div:TF (match_operand:TF 1 "register_operand" "f")
2415: (match_operand:TF 2 "register_operand" "f")))]
2416: "TARGET_FPU"
2417: "fdivq %1,%2,%0"
2418: [(set_attr "type" "fpdiv")])
2419:
2420: (define_insn "divdf3"
2421: [(set (match_operand:DF 0 "register_operand" "=f")
2422: (div:DF (match_operand:DF 1 "register_operand" "f")
2423: (match_operand:DF 2 "register_operand" "f")))]
2424: "TARGET_FPU"
2425: "fdivd %1,%2,%0"
2426: [(set_attr "type" "fpdiv")])
2427:
2428: (define_insn "divsf3"
2429: [(set (match_operand:SF 0 "register_operand" "=f")
2430: (div:SF (match_operand:SF 1 "register_operand" "f")
2431: (match_operand:SF 2 "register_operand" "f")))]
2432: "TARGET_FPU"
2433: "fdivs %1,%2,%0"
2434: [(set_attr "type" "fpdiv")])
2435:
2436: (define_insn "negtf2"
2437: [(set (match_operand:TF 0 "register_operand" "=f,f")
2438: (neg:TF (match_operand:TF 1 "register_operand" "0,f")))]
2439: "TARGET_FPU"
2440: "@
2441: fnegs %0,%0
2442: fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2443: [(set_attr "type" "fp")
2444: (set_attr "length" "1,4")])
2445:
2446: (define_insn "negdf2"
2447: [(set (match_operand:DF 0 "register_operand" "=f,f")
2448: (neg:DF (match_operand:DF 1 "register_operand" "0,f")))]
2449: "TARGET_FPU"
2450: "@
2451: fnegs %0,%0
2452: fnegs %1,%0\;fmovs %R1,%R0"
2453: [(set_attr "type" "fp")
2454: (set_attr "length" "1,2")])
2455:
2456: (define_insn "negsf2"
2457: [(set (match_operand:SF 0 "register_operand" "=f")
2458: (neg:SF (match_operand:SF 1 "register_operand" "f")))]
2459: "TARGET_FPU"
2460: "fnegs %1,%0"
2461: [(set_attr "type" "fp")])
2462:
2463: (define_insn "abstf2"
2464: [(set (match_operand:TF 0 "register_operand" "=f,f")
2465: (abs:TF (match_operand:TF 1 "register_operand" "0,f")))]
2466: "TARGET_FPU"
2467: "@
2468: fabss %0,%0
2469: fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0"
2470: [(set_attr "type" "fp")
2471: (set_attr "length" "1,4")])
2472:
2473: (define_insn "absdf2"
2474: [(set (match_operand:DF 0 "register_operand" "=f,f")
2475: (abs:DF (match_operand:DF 1 "register_operand" "0,f")))]
2476: "TARGET_FPU"
2477: "@
2478: fabss %0,%0
2479: fabss %1,%0\;fmovs %R1,%R0"
2480: [(set_attr "type" "fp")
2481: (set_attr "length" "1,2")])
2482:
2483: (define_insn "abssf2"
2484: [(set (match_operand:SF 0 "register_operand" "=f")
2485: (abs:SF (match_operand:SF 1 "register_operand" "f")))]
2486: "TARGET_FPU"
2487: "fabss %1,%0"
2488: [(set_attr "type" "fp")])
2489:
2490: (define_insn "sqrttf2"
2491: [(set (match_operand:TF 0 "register_operand" "=f")
2492: (sqrt:TF (match_operand:TF 1 "register_operand" "f")))]
2493: "TARGET_FPU"
2494: "fsqrtq %1,%0"
2495: [(set_attr "type" "fpsqrt")])
2496:
2497: (define_insn "sqrtdf2"
2498: [(set (match_operand:DF 0 "register_operand" "=f")
2499: (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
2500: "TARGET_FPU"
2501: "fsqrtd %1,%0"
2502: [(set_attr "type" "fpsqrt")])
2503:
2504: (define_insn "sqrtsf2"
2505: [(set (match_operand:SF 0 "register_operand" "=f")
2506: (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
2507: "TARGET_FPU"
2508: "fsqrts %1,%0"
2509: [(set_attr "type" "fpsqrt")])
2510:
2511: ;;- arithmetic shift instructions
2512:
2513: ;; We can trivially handle shifting the constant 1 by 64 bits.
2514: ;; For other shifts we use the library routine.
2515: ;; ??? Questionable, we can do better than this can't we?
2516: (define_expand "ashldi3"
2517: [(parallel [(set (match_operand:DI 0 "register_operand" "")
2518: (ashift:DI (match_operand:DI 1 "const_double_operand" "")
2519: (match_operand:SI 2 "register_operand" "")))
2520: (clobber (reg:SI 0))])]
2521: ""
2522: "
2523: {
2524: if (GET_CODE (operands[1]) == CONST_DOUBLE
2525: && CONST_DOUBLE_HIGH (operands[1]) == 0
2526: && CONST_DOUBLE_LOW (operands[1]) == 1)
2527: operands[1] = const1_rtx;
2528: else if (operands[1] != const1_rtx)
2529: FAIL;
2530: }")
2531:
2532: ;; ??? Questionable, we can do better than this can't we?
2533: (define_insn ""
2534: [(set (match_operand:DI 0 "register_operand" "=&r")
2535: (ashift:DI (const_int 1)
2536: (match_operand:SI 1 "register_operand" "r")))
2537: (clobber (reg:SI 0))]
2538: ""
2539: "subcc %1,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%1,%R0\;sll %0,%1,%0"
2540: [(set_attr "type" "multi")
2541: (set_attr "length" "5")])
2542:
2543: (define_insn "ashlsi3"
2544: [(set (match_operand:SI 0 "register_operand" "=r")
2545: (ashift:SI (match_operand:SI 1 "register_operand" "r")
2546: (match_operand:SI 2 "arith_operand" "rI")))]
2547: ""
2548: "sll %1,%2,%0")
2549:
2550: (define_expand "lshldi3"
2551: [(parallel [(set (match_operand:DI 0 "register_operand" "")
2552: (lshift:DI (match_operand:DI 1 "register_operand" "")
2553: (match_operand:DI 2 "const_int_operand" "")))
2554: (clobber (match_scratch:SI 3 ""))])]
2555: ""
2556: "
2557: {
2558: if (GET_CODE (operands[2]) != CONST_INT)
2559: FAIL;
2560: }")
2561:
2562: (define_insn ""
2563: [(set (match_operand:DI 0 "register_operand" "=r")
2564: (lshift:DI (match_operand:DI 1 "register_operand" "r")
2565: (match_operand:DI 2 "const_int_operand" "I")))
2566: (clobber (match_scratch:SI 3 "=r"))]
2567: "INTVAL (operands[2]) < 32"
2568: "*
2569: {
2570: operands[4] = GEN_INT (32 - INTVAL (operands[2]));
2571: return \"srl %R1,%4,%3\;sll %R1,%2,%R0\;sll %1,%2,%0\;or %3,%0,%0\";
2572: }"
2573: [(set_attr "type" "multi")
2574: (set_attr "length" "4")])
2575:
2576: (define_insn ""
2577: [(set (match_operand:DI 0 "register_operand" "=r")
2578: (lshift:DI (match_operand:DI 1 "register_operand" "r")
2579: (match_operand:DI 2 "const_int_operand" "I")))
2580: (clobber (match_scratch:SI 3 "=X"))]
2581: "INTVAL (operands[2]) >= 32"
2582: "*
2583: {
2584: operands[4] = GEN_INT (INTVAL (operands[2]) - 32);
2585: return \"sll %R1,%4,%0\;mov %%g0,%R0\";
2586: }"
2587: [(set_attr "type" "multi")
2588: (set_attr "length" "2")])
2589:
2590: (define_insn "ashrsi3"
2591: [(set (match_operand:SI 0 "register_operand" "=r")
2592: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
2593: (match_operand:SI 2 "arith_operand" "rI")))]
2594: ""
2595: "sra %1,%2,%0")
2596:
2597: (define_insn "lshrsi3"
2598: [(set (match_operand:SI 0 "register_operand" "=r")
2599: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
2600: (match_operand:SI 2 "arith_operand" "rI")))]
2601: ""
2602: "srl %1,%2,%0")
2603:
2604: (define_expand "lshrdi3"
2605: [(parallel [(set (match_operand:DI 0 "register_operand" "")
2606: (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
2607: (match_operand:DI 2 "const_int_operand" "")))
2608: (clobber (match_scratch:SI 3 ""))])]
2609: ""
2610: "
2611: {
2612: if (GET_CODE (operands[2]) != CONST_INT)
2613: FAIL;
2614: }")
2615:
2616: (define_insn ""
2617: [(set (match_operand:DI 0 "register_operand" "=r")
2618: (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
2619: (match_operand:DI 2 "const_int_operand" "I")))
2620: (clobber (match_scratch:SI 3 "=r"))]
2621: "INTVAL (operands[2]) < 32"
2622: "*
2623: {
2624: operands[4] = GEN_INT (32 - INTVAL (operands[2]));
2625: return \"sll %1,%4,%3\;srl %1,%2,%0\;srl %R1,%2,%R0\;or %3,%R0,%R0\";
2626: }"
2627: [(set_attr "type" "multi")
2628: (set_attr "length" "4")])
2629:
2630: (define_insn ""
2631: [(set (match_operand:DI 0 "register_operand" "=r")
2632: (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
2633: (match_operand:DI 2 "const_int_operand" "I")))
2634: (clobber (match_scratch:SI 3 "=X"))]
2635: "INTVAL (operands[2]) >= 32"
2636: "*
2637: {
2638: operands[4] = GEN_INT (INTVAL (operands[2]) - 32);
2639: return \"srl %1,%4,%R0\;mov %%g0,%0\";
2640: }"
2641: [(set_attr "type" "multi")
2642: (set_attr "length" "2")])
2643:
2644: ;; Unconditional and other jump instructions
2645: ;; On the Sparc, by setting the annul bit on an unconditional branch, the
2646: ;; following insn is never executed. This saves us a nop. Dbx does not
2647: ;; handle such branches though, so we only use them when optimizing.
2648: (define_insn "jump"
2649: [(set (pc) (label_ref (match_operand 0 "" "")))]
2650: ""
2651: "b%* %l0%("
2652: [(set_attr "type" "uncond_branch")])
2653:
2654: (define_expand "tablejump"
2655: [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2656: (use (label_ref (match_operand 1 "" "")))])]
2657: ""
2658: "
2659: {
2660: /* We need to use the PC value in %o7 that was set up when the address
2661: of the label was loaded into a register, so we need different RTL. */
2662: if (flag_pic)
2663: {
2664: emit_insn (gen_pic_tablejump (operands[0], operands[1]));
2665: DONE;
2666: }
2667: }")
2668:
2669: (define_insn "pic_tablejump"
2670: [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2671: (use (label_ref (match_operand 1 "" "")))
2672: (use (reg:SI 15))]
2673: ""
2674: "jmp %%o7+%0%#"
2675: [(set_attr "type" "uncond_branch")])
2676:
2677: (define_insn ""
2678: [(set (pc) (match_operand:SI 0 "address_operand" "p"))
2679: (use (label_ref (match_operand 1 "" "")))]
2680: ""
2681: "jmp %a0%#"
2682: [(set_attr "type" "uncond_branch")])
2683:
2684: (define_insn ""
2685: [(set (pc) (label_ref (match_operand 0 "" "")))
2686: (set (reg:SI 15) (label_ref (match_dup 0)))]
2687: ""
2688: "call %l0%#"
2689: [(set_attr "type" "uncond_branch")])
2690:
2691: ;; This pattern recognizes the "instruction" that appears in
2692: ;; a function call that wants a structure value,
2693: ;; to inform the called function if compiled with Sun CC.
2694: ;(define_insn ""
2695: ; [(match_operand:SI 0 "immediate_operand" "")]
2696: ; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
2697: ; "unimp %0"
2698: ; [(set_attr "type" "marker")])
2699:
2700: ;;- jump to subroutine
2701: (define_expand "call"
2702: ;; Note that this expression is not used for generating RTL.
2703: ;; All the RTL is generated explicitly below.
2704: [(call (match_operand:SI 0 "call_operand" "")
2705: (match_operand 3 "" "i"))]
2706: ;; operands[2] is next_arg_register
2707: ;; operands[3] is struct_value_size_rtx.
2708: ""
2709: "
2710: {
2711: rtx fn_rtx, nregs_rtx;
2712:
2713: if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
2714: {
2715: /* This is really a PIC sequence. We want to represent
2716: it as a funny jump so it's delay slots can be filled.
2717:
2718: ??? But if this really *is* a CALL, will not it clobber the
2719: call-clobbered registers? We lose this if it is a JUMP_INSN.
2720: Why cannot we have delay slots filled if it were a CALL? */
2721:
2722: if (INTVAL (operands[3]) > 0)
2723: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2724: gen_rtx (SET, VOIDmode, pc_rtx,
2725: XEXP (operands[0], 0)),
2726: operands[3],
2727: gen_rtx (CLOBBER, VOIDmode,
2728: gen_rtx (REG, SImode, 15)))));
2729: else
2730: emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2731: gen_rtx (SET, VOIDmode, pc_rtx,
2732: XEXP (operands[0], 0)),
2733: gen_rtx (CLOBBER, VOIDmode,
2734: gen_rtx (REG, SImode, 15)))));
2735: goto finish_call;
2736: }
2737:
2738: fn_rtx = operands[0];
2739:
2740: /* Count the number of parameter registers being used by this call.
2741: if that argument is NULL, it means we are using them all, which
2742: means 6 on the sparc. */
2743: #if 0
2744: if (operands[2])
2745: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
2746: else
2747: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2748: #else
2749: nregs_rtx = const0_rtx;
2750: #endif
2751:
2752: if (INTVAL (operands[3]) > 0)
2753: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
2754: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2755: operands[3],
2756: gen_rtx (CLOBBER, VOIDmode,
2757: gen_rtx (REG, SImode, 15)))));
2758: else
2759: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2760: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2761: gen_rtx (CLOBBER, VOIDmode,
2762: gen_rtx (REG, SImode, 15)))));
2763:
2764: finish_call:
2765: #if 0
2766: /* If this call wants a structure value,
2767: emit an unimp insn to let the called function know about this. */
2768: if (INTVAL (operands[3]) > 0)
2769: {
2770: rtx insn = emit_insn (operands[3]);
2771: SCHED_GROUP_P (insn) = 1;
2772: }
2773: #endif
2774:
2775: DONE;
2776: }")
2777:
2778: (define_insn ""
2779: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2780: (match_operand 1 "" ""))
2781: (clobber (reg:SI 15))]
2782: ;;- Do not use operand 1 for most machines.
2783: ""
2784: "*
2785: {
2786: return \"call %a0,%1%#\";
2787: }"
2788: [(set_attr "type" "call")])
2789:
2790: ;; This is a call that wants a structure value.
2791: (define_insn ""
2792: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
2793: (match_operand 1 "" ""))
2794: (match_operand 2 "immediate_operand" "")
2795: (clobber (reg:SI 15))]
2796: ;;- Do not use operand 1 for most machines.
2797: "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
2798: "*
2799: {
2800: return \"call %a0,%1\;nop\;unimp %2\";
2801: }"
2802: [(set_attr "type" "call_no_delay_slot")])
2803:
2804: (define_expand "call_value"
2805: [(set (match_operand 0 "register_operand" "=rf")
2806: (call (match_operand:SI 1 "" "")
2807: (match_operand 4 "" "")))]
2808: ;; operand 3 is next_arg_register
2809: ""
2810: "
2811: {
2812: rtx fn_rtx, nregs_rtx;
2813: rtvec vec;
2814:
2815: fn_rtx = operands[1];
2816:
2817: #if 0
2818: if (operands[3])
2819: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
2820: else
2821: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2822: #else
2823: nregs_rtx = const0_rtx;
2824: #endif
2825:
2826: vec = gen_rtvec (2,
2827: gen_rtx (SET, VOIDmode, operands[0],
2828: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2829: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 15)));
2830:
2831: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2832:
2833: DONE;
2834: }")
2835:
2836: (define_insn ""
2837: [(set (match_operand 0 "" "=rf")
2838: (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS"))
2839: (match_operand 2 "" "")))
2840: (clobber (reg:SI 15))]
2841: ;;- Do not use operand 2 for most machines.
2842: ""
2843: "*
2844: {
2845: return \"call %a1,%2%#\";
2846: }"
2847: [(set_attr "type" "call")])
2848:
2849: (define_expand "untyped_call"
2850: [(parallel [(call (match_operand:SI 0 "call_operand" "")
2851: (const_int 0))
2852: (match_operand:BLK 1 "memory_operand" "")
2853: (match_operand 2 "" "")
2854: (clobber (reg:SI 15))])]
2855: ""
2856: "
2857: {
2858: operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
2859: }")
2860:
2861: ;; Make a call followed by two nops in case the function being called
2862: ;; returns a structure value and expects to skip an unimp instruction.
2863:
2864: (define_insn ""
2865: [(call (mem:SI (match_operand:SI 0 "call_operand_address" "rS"))
2866: (const_int 0))
2867: (match_operand:DI 1 "memory_operand" "o")
2868: (match_operand 2 "" "")
2869: (clobber (reg:SI 15))]
2870: ""
2871: "*
2872: {
2873: operands[2] = adj_offsettable_operand (operands[1], 8);
2874: return \"call %a0,0\;nop\;nop\;std %%o0,%1\;st %%f0,%2\";
2875: }"
2876: [(set_attr "type" "multi")])
2877:
2878: ;; Prepare to return any type including a structure value.
2879:
2880: (define_expand "untyped_return"
2881: [(match_operand:BLK 0 "memory_operand" "")
2882: (match_operand 1 "" "")]
2883: ""
2884: "
2885: {
2886: rtx valreg1 = gen_rtx (REG, DImode, 24);
2887: rtx valreg2 = gen_rtx (REG, DFmode, 32);
2888: rtx result = operands[0];
2889: rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
2890: rtx value = gen_reg_rtx (SImode);
2891:
2892: /* Fetch the instruction where we will return to and see if it's an unimp
2893: instruction (the most significant 10 bits will be zero). If so,
2894: update the return address to skip the unimp instruction. */
2895: emit_move_insn (value,
2896: gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
2897: emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
2898: emit_insn (gen_update_return (rtnreg, value));
2899:
2900: /* Reload the function value registers. */
2901: emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
2902: emit_move_insn (valreg2,
2903: change_address (result, DFmode,
2904: plus_constant (XEXP (result, 0), 8)));
2905:
2906: /* Put USE insns before the return. */
2907: emit_insn (gen_rtx (USE, VOIDmode, valreg1));
2908: emit_insn (gen_rtx (USE, VOIDmode, valreg2));
2909:
2910: /* Construct the return. */
2911: expand_null_return ();
2912:
2913: DONE;
2914: }")
2915:
2916: ;; This is a bit of a hack. We're incrementing a fixed register (%i7),
2917: ;; and parts of the compiler don't want to believe that the add is needed.
2918:
2919: (define_insn "update_return"
2920: [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2921: (match_operand:SI 1 "register_operand" "r")] 0)]
2922: ""
2923: "cmp %1,0\;be,a .+8\;add %0,4,%0"
2924: [(set_attr "type" "multi")])
2925:
2926: (define_insn "return"
2927: [(return)]
2928: "! TARGET_EPILOGUE"
2929: "* return output_return (operands);"
2930: [(set_attr "type" "multi")])
2931:
2932: (define_insn "nop"
2933: [(const_int 0)]
2934: ""
2935: "nop")
2936:
2937: (define_insn "indirect_jump"
2938: [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
2939: ""
2940: "jmp %a0%#"
2941: [(set_attr "type" "uncond_branch")])
2942:
2943: (define_expand "nonlocal_goto"
2944: [(match_operand:SI 0 "general_operand" "")
2945: (match_operand:SI 1 "general_operand" "")
2946: (match_operand:SI 2 "general_operand" "")
2947: (match_operand:SI 3 "" "")]
2948: ""
2949: "
2950: {
2951: /* Trap instruction to flush all the registers window. */
2952: emit_insn (gen_flush_register_windows ());
2953: /* Load the fp value for the containing fn into %fp.
2954: This is needed because operands[2] refers to %fp.
2955: Virtual register instantiation fails if the virtual %fp isn't set from a
2956: register. Thus we must copy operands[0] into a register if it isn't
2957: already one. */
2958: if (GET_CODE (operands[0]) != REG)
2959: operands[0] = force_reg (SImode, operands[0]);
2960: emit_move_insn (virtual_stack_vars_rtx, operands[0]);
2961: /* Find the containing function's current nonlocal goto handler,
2962: which will do any cleanups and then jump to the label. */
2963: emit_move_insn (gen_rtx (REG, SImode, 8), operands[1]);
2964: /* Restore %fp from stack pointer value for containing function.
2965: The restore insn that follows will move this to %sp,
2966: and reload the appropriate value into %fp. */
2967: emit_move_insn (frame_pointer_rtx, operands[2]);
2968: /* Put in the static chain register the nonlocal label address. */
2969: emit_move_insn (static_chain_rtx, operands[3]);
2970: /* USE of frame_pointer_rtx added for consistency; not clear if
2971: really needed. */
2972: emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
2973: emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
2974: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
2975: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 8)));
2976: /* Return, restoring reg window and jumping to goto handler. */
2977: emit_insn (gen_goto_handler_and_restore ());
2978: DONE;
2979: }")
2980:
2981: ;; Special trap insn to flush register windows.
2982: (define_insn "flush_register_windows"
2983: [(unspec_volatile [(const_int 0)] 0)]
2984: ""
2985: "ta 3"
2986: [(set_attr "type" "misc")])
2987:
2988: (define_insn "goto_handler_and_restore"
2989: [(unspec_volatile [(const_int 0)] 1)]
2990: ""
2991: "jmp %%o0+0\;restore"
2992: [(set_attr "type" "misc")
2993: (set_attr "length" "2")])
2994:
2995: ;; find first set.
2996:
2997: ;; The scan instruction searches from the most significant bit while ffs
2998: ;; searches from the least significant bit. The bit index and treatment of
2999: ;; zero also differ. It takes at least 7 instructions to get the proper
3000: ;; result. Here is an obvious 8 instruction seequence.
3001:
3002: (define_insn "ffssi2"
3003: [(set (match_operand:SI 0 "register_operand" "=&r")
3004: (ffs:SI (match_operand:SI 1 "register_operand" "r")))
3005: (clobber (match_scratch:SI 2 "=&r"))]
3006: "TARGET_SPARCLITE"
3007: "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"
3008: [(set_attr "type" "multi")
3009: (set_attr "length" "8")])
3010:
3011: ;; Split up troublesome insns for better scheduling. */
3012:
3013: ;; The following patterns are straightforward. They can be applied
3014: ;; either before or after register allocation.
3015:
3016: (define_split
3017: [(set (match_operator 0 "memop" [(match_operand:SI 1 "symbolic_operand" "")])
3018: (match_operand 2 "reg_or_0_operand" ""))
3019: (clobber (match_operand:SI 3 "register_operand" ""))]
3020: "! flag_pic"
3021: [(set (match_dup 3) (high:SI (match_dup 1)))
3022: (set (match_op_dup 0 [(lo_sum:SI (match_dup 3) (match_dup 1))])
3023: (match_dup 2))]
3024: "")
3025:
3026: (define_split
3027: [(set (match_operator 0 "memop"
3028: [(match_operand:SI 1 "immediate_operand" "")])
3029: (match_operand 2 "general_operand" ""))
3030: (clobber (match_operand:SI 3 "register_operand" ""))]
3031: "flag_pic"
3032: [(set (match_op_dup 0 [(match_dup 1)])
3033: (match_dup 2))]
3034: "
3035: {
3036: operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]),
3037: operands[3], 0);
3038: }")
3039:
3040: (define_split
3041: [(set (match_operand 0 "register_operand" "")
3042: (match_operator 1 "memop"
3043: [(match_operand:SI 2 "immediate_operand" "")]))]
3044: "flag_pic"
3045: [(set (match_dup 0)
3046: (match_op_dup 1 [(match_dup 2)]))]
3047: "
3048: {
3049: operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]),
3050: operands[0], 0);
3051: }")
3052:
3053: ;; Sign- and Zero-extend operations can have symbolic memory operands.
3054:
3055: (define_split
3056: [(set (match_operand 0 "register_operand" "")
3057: (match_operator 1 "extend_op"
3058: [(match_operator 2 "memop"
3059: [(match_operand:SI 3 "immediate_operand" "")])]))]
3060: "flag_pic"
3061: [(set (match_dup 0)
3062: (match_op_dup 1 [(match_op_dup 2 [(match_dup 3)])]))]
3063: "
3064: {
3065: operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]),
3066: operands[0], 0);
3067: }")
3068:
3069: (define_split
3070: [(set (match_operand:SI 0 "register_operand" "")
3071: (match_operand:SI 1 "immediate_operand" ""))]
3072: "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
3073: || GET_CODE (operands[1]) == CONST
3074: || GET_CODE (operands[1]) == LABEL_REF)"
3075: [(set (match_dup 0) (high:SI (match_dup 1)))
3076: (set (match_dup 0)
3077: (lo_sum:SI (match_dup 0) (match_dup 1)))]
3078: "")
3079:
3080: ;; LABEL_REFs are not modified by `legitimize_pic_address`
3081: ;; so do not recurse infinitely in the PIC case.
3082: (define_split
3083: [(set (match_operand:SI 0 "register_operand" "")
3084: (match_operand:SI 1 "immediate_operand" ""))]
3085: "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
3086: || GET_CODE (operands[1]) == CONST)"
3087: [(set (match_dup 0) (match_dup 1))]
3088: "
3089: {
3090: operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0);
3091: }")
3092:
3093: ;; These split sne/seq insns. The forms of the resulting insns are
3094: ;; somewhat bogus, but they avoid extra patterns and show data dependency.
3095: ;; Nothing will look at these in detail after splitting has occurred.
3096:
3097: (define_split
3098: [(set (match_operand:SI 0 "register_operand" "")
3099: (ne:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
3100: (clobber (reg:CC 0))]
3101: ""
3102: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3103: (const_int 0)))
3104: (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
3105: "")
3106:
3107: (define_split
3108: [(set (match_operand:SI 0 "register_operand" "")
3109: (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
3110: (const_int 0))))
3111: (clobber (reg:CC 0))]
3112: ""
3113: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3114: (const_int 0)))
3115: (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
3116: "")
3117:
3118: (define_split
3119: [(set (match_operand:SI 0 "register_operand" "")
3120: (eq:SI (match_operand:SI 1 "register_operand" "") (const_int 0)))
3121: (clobber (reg:CC 0))]
3122: ""
3123: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3124: (const_int 0)))
3125: (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
3126: "")
3127:
3128: (define_split
3129: [(set (match_operand:SI 0 "register_operand" "")
3130: (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
3131: (const_int 0))))
3132: (clobber (reg:CC 0))]
3133: ""
3134: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3135: (const_int 0)))
3136: (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
3137: "")
3138:
3139: (define_split
3140: [(set (match_operand:SI 0 "register_operand" "")
3141: (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
3142: (const_int 0))
3143: (match_operand:SI 2 "register_operand" "")))
3144: (clobber (reg:CC 0))]
3145: ""
3146: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3147: (const_int 0)))
3148: (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
3149: (match_dup 2)))]
3150: "")
3151:
3152: (define_split
3153: [(set (match_operand:SI 0 "register_operand" "")
3154: (minus:SI (match_operand:SI 2 "register_operand" "")
3155: (ne:SI (match_operand:SI 1 "register_operand" "")
3156: (const_int 0))))
3157: (clobber (reg:CC 0))]
3158: ""
3159: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3160: (const_int 0)))
3161: (set (match_dup 0) (minus:SI (match_dup 2)
3162: (ltu:SI (reg:CC 0) (const_int 0))))]
3163: "")
3164:
3165: (define_split
3166: [(set (match_operand:SI 0 "register_operand" "")
3167: (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
3168: (const_int 0))
3169: (match_operand:SI 2 "register_operand" "")))
3170: (clobber (reg:CC 0))]
3171: ""
3172: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3173: (const_int 0)))
3174: (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
3175: (match_dup 2)))]
3176: "")
3177:
3178: (define_split
3179: [(set (match_operand:SI 0 "register_operand" "")
3180: (minus:SI (match_operand:SI 2 "register_operand" "")
3181: (eq:SI (match_operand:SI 1 "register_operand" "")
3182: (const_int 0))))
3183: (clobber (reg:CC 0))]
3184: ""
3185: [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
3186: (const_int 0)))
3187: (set (match_dup 0) (minus:SI (match_dup 2)
3188: (geu:SI (reg:CC 0) (const_int 0))))]
3189: "")
3190:
3191: ;; Peepholes go at the end.
3192:
3193: ;; Optimize consecutive loads or stores into ldd and std when possible.
3194: ;; The conditions in which we do this are very restricted and are
3195: ;; explained in the code for {registers,memory}_ok_for_ldd functions.
3196:
3197: (define_peephole
3198: [(set (match_operand:SI 0 "register_operand" "=rf")
3199: (match_operand:SI 1 "memory_operand" ""))
3200: (set (match_operand:SI 2 "register_operand" "=rf")
3201: (match_operand:SI 3 "memory_operand" ""))]
3202: "registers_ok_for_ldd_peep (operands[0], operands[2])
3203: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
3204: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
3205: "ldd %1,%0")
3206:
3207: (define_peephole
3208: [(set (match_operand:SI 0 "memory_operand" "")
3209: (match_operand:SI 1 "register_operand" "rf"))
3210: (set (match_operand:SI 2 "memory_operand" "")
3211: (match_operand:SI 3 "register_operand" "rf"))]
3212: "registers_ok_for_ldd_peep (operands[1], operands[3])
3213: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
3214: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
3215: "std %1,%0")
3216:
3217: (define_peephole
3218: [(set (match_operand:SF 0 "register_operand" "=fr")
3219: (match_operand:SF 1 "memory_operand" ""))
3220: (set (match_operand:SF 2 "register_operand" "=fr")
3221: (match_operand:SF 3 "memory_operand" ""))]
3222: "registers_ok_for_ldd_peep (operands[0], operands[2])
3223: && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
3224: && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
3225: "ldd %1,%0")
3226:
3227: (define_peephole
3228: [(set (match_operand:SF 0 "memory_operand" "")
3229: (match_operand:SF 1 "register_operand" "fr"))
3230: (set (match_operand:SF 2 "memory_operand" "")
3231: (match_operand:SF 3 "register_operand" "fr"))]
3232: "registers_ok_for_ldd_peep (operands[1], operands[3])
3233: && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
3234: && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
3235: "std %1,%0")
3236:
3237: (define_peephole
3238: [(set (match_operand:SI 0 "register_operand" "=rf")
3239: (match_operand:SI 1 "memory_operand" ""))
3240: (set (match_operand:SI 2 "register_operand" "=rf")
3241: (match_operand:SI 3 "memory_operand" ""))]
3242: "registers_ok_for_ldd_peep (operands[2], operands[0])
3243: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
3244: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
3245: "ldd %3,%2")
3246:
3247: (define_peephole
3248: [(set (match_operand:SI 0 "memory_operand" "")
3249: (match_operand:SI 1 "register_operand" "rf"))
3250: (set (match_operand:SI 2 "memory_operand" "")
3251: (match_operand:SI 3 "register_operand" "rf"))]
3252: "registers_ok_for_ldd_peep (operands[3], operands[1])
3253: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
3254: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
3255: "std %3,%2")
3256:
3257: (define_peephole
3258: [(set (match_operand:SF 0 "register_operand" "=fr")
3259: (match_operand:SF 1 "memory_operand" ""))
3260: (set (match_operand:SF 2 "register_operand" "=fr")
3261: (match_operand:SF 3 "memory_operand" ""))]
3262: "registers_ok_for_ldd_peep (operands[2], operands[0])
3263: && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
3264: && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
3265: "ldd %3,%2")
3266:
3267: (define_peephole
3268: [(set (match_operand:SF 0 "memory_operand" "")
3269: (match_operand:SF 1 "register_operand" "fr"))
3270: (set (match_operand:SF 2 "memory_operand" "")
3271: (match_operand:SF 3 "register_operand" "fr"))]
3272: "registers_ok_for_ldd_peep (operands[3], operands[1])
3273: && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
3274: && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
3275: "std %3,%2")
3276:
3277: ;; Optimize the case of following a reg-reg move with a test
3278: ;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
3279: ;; This can result from a float to fix conversion.
3280:
3281: (define_peephole
3282: [(set (match_operand:SI 0 "register_operand" "=r")
3283: (match_operand:SI 1 "register_operand" "r"))
3284: (set (reg:CC 0)
3285: (compare:CC (match_operand:SI 2 "register_operand" "r")
3286: (const_int 0)))]
3287: "(rtx_equal_p (operands[2], operands[0])
3288: || rtx_equal_p (operands[2], operands[1]))
3289: && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
3290: "orcc %1,%%g0,%0")
3291:
3292: ;; Do {sign,zero}-extended compares somewhat more efficiently.
3293: ;; ??? Is this now the Right Way to do this? Or will SCRATCH
3294: ;; eventually have some impact here?
3295:
3296: (define_peephole
3297: [(set (match_operand:HI 0 "register_operand" "")
3298: (match_operand:HI 1 "memory_operand" ""))
3299: (set (match_operand:SI 2 "register_operand" "")
3300: (sign_extend:SI (match_dup 0)))
3301: (set (reg:CC 0)
3302: (compare:CC (match_dup 2)
3303: (const_int 0)))]
3304: ""
3305: "ldsh %1,%0\;orcc %0,%%g0,%2")
3306:
3307: (define_peephole
3308: [(set (match_operand:QI 0 "register_operand" "")
3309: (match_operand:QI 1 "memory_operand" ""))
3310: (set (match_operand:SI 2 "register_operand" "")
3311: (sign_extend:SI (match_dup 0)))
3312: (set (reg:CC 0)
3313: (compare:CC (match_dup 2)
3314: (const_int 0)))]
3315: ""
3316: "ldsb %1,%0\;orcc %0,%%g0,%2")
3317:
3318: (define_peephole
3319: [(set (match_operand:HI 0 "register_operand" "")
3320: (match_operand:HI 1 "memory_operand" ""))
3321: (set (match_operand:SI 2 "register_operand" "")
3322: (sign_extend:SI (match_dup 0)))]
3323: "dead_or_set_p (insn, operands[0])"
3324: "*
3325: {
3326: warning (\"bad peephole\");
3327: if (! MEM_VOLATILE_P (operands[1]))
3328: abort ();
3329: return \"ldsh %1,%2\";
3330: }")
3331:
3332: (define_peephole
3333: [(set (match_operand:QI 0 "register_operand" "")
3334: (match_operand:QI 1 "memory_operand" ""))
3335: (set (match_operand:SI 2 "register_operand" "")
3336: (sign_extend:SI (match_dup 0)))]
3337: "dead_or_set_p (insn, operands[0])"
3338: "*
3339: {
3340: warning (\"bad peephole\");
3341: if (! MEM_VOLATILE_P (operands[1]))
3342: abort ();
3343: return \"ldsb %1,%2\";
3344: }")
3345:
3346: ;; Floating-point move peepholes
3347:
3348: (define_peephole
3349: [(set (match_operand:SI 0 "register_operand" "=r")
3350: (lo_sum:SI (match_dup 0)
3351: (match_operand:SI 1 "immediate_operand" "i")))
3352: (set (match_operand:DF 2 "register_operand" "=fr")
3353: (mem:DF (match_dup 0)))]
3354: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
3355: "*
3356: {
3357: /* Go by way of output_move_double in case the register in operand 2
3358: is not properly aligned for ldd. */
3359: operands[1] = gen_rtx (MEM, DFmode,
3360: gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
3361: operands[0] = operands[2];
3362: return output_move_double (operands);
3363: }")
3364:
3365: (define_peephole
3366: [(set (match_operand:SI 0 "register_operand" "=r")
3367: (lo_sum:SI (match_dup 0)
3368: (match_operand:SI 1 "immediate_operand" "i")))
3369: (set (match_operand:SF 2 "register_operand" "=fr")
3370: (mem:SF (match_dup 0)))]
3371: "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
3372: "ld [%0+%%lo(%a1)],%2")
3373:
3374: ;; Return peepholes. First the "normal" ones
3375:
3376: ;; ??? There are QImode, HImode, and SImode versions of this pattern.
3377: ;; It might be possible to write one more general pattern instead of three.
3378:
3379: (define_insn ""
3380: [(set (match_operand:QI 0 "restore_operand" "")
3381: (match_operand:QI 1 "arith_operand" "rI"))
3382: (return)]
3383: "! TARGET_EPILOGUE"
3384: "*
3385: {
3386: if (current_function_returns_struct)
3387: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3388: else
3389: return \"ret\;restore %%g0,%1,%Y0\";
3390: }"
3391: [(set_attr "type" "multi")])
3392:
3393: (define_insn ""
3394: [(set (match_operand:HI 0 "restore_operand" "")
3395: (match_operand:HI 1 "arith_operand" "rI"))
3396: (return)]
3397: "! TARGET_EPILOGUE"
3398: "*
3399: {
3400: if (current_function_returns_struct)
3401: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3402: else
3403: return \"ret\;restore %%g0,%1,%Y0\";
3404: }"
3405: [(set_attr "type" "multi")])
3406:
3407: (define_insn ""
3408: [(set (match_operand:SI 0 "restore_operand" "")
3409: (match_operand:SI 1 "arith_operand" "rI"))
3410: (return)]
3411: "! TARGET_EPILOGUE"
3412: "*
3413: {
3414: if (current_function_returns_struct)
3415: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3416: else
3417: return \"ret\;restore %%g0,%1,%Y0\";
3418: }"
3419: [(set_attr "type" "multi")])
3420:
3421: ;; The following pattern is only generated by delayed-branch scheduling,
3422: ;; when the insn winds up in the epilogue. This can only happen when
3423: ;; ! TARGET_FPU because otherwise fp return values are in %f0.
3424: (define_insn ""
3425: [(set (match_operand:SF 0 "restore_operand" "r")
3426: (match_operand:SF 1 "register_operand" "r"))
3427: (return)]
3428: "! TARGET_FPU && ! TARGET_EPILOGUE"
3429: "*
3430: {
3431: if (current_function_returns_struct)
3432: return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
3433: else
3434: return \"ret\;restore %%g0,%1,%Y0\";
3435: }"
3436: [(set_attr "type" "multi")])
3437:
3438: (define_insn ""
3439: [(set (match_operand:SI 0 "restore_operand" "")
3440: (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3441: (match_operand:SI 2 "arith_operand" "rI")))
3442: (return)]
3443: "! TARGET_EPILOGUE"
3444: "*
3445: {
3446: if (current_function_returns_struct)
3447: return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
3448: else
3449: return \"ret\;restore %r1,%2,%Y0\";
3450: }"
3451: [(set_attr "type" "multi")])
3452:
3453: ;; Turned off because it should never match (subtracting a constant
3454: ;; is turned into addition) and because it would do the wrong thing
3455: ;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
3456: ;;(define_insn ""
3457: ;; [(set (match_operand:SI 0 "restore_operand" "")
3458: ;; (minus:SI (match_operand:SI 1 "register_operand" "r")
3459: ;; (match_operand:SI 2 "small_int" "I")))
3460: ;; (return)]
3461: ;; "! TARGET_EPILOGUE"
3462: ;; "ret\;restore %1,-(%2),%Y0"
3463: ;; [(set_attr "type" "multi")])
3464:
3465: ;; The following pattern is only generated by delayed-branch scheduling,
3466: ;; when the insn winds up in the epilogue.
3467: (define_insn ""
3468: [(set (reg:SF 32)
3469: (match_operand:SF 0 "register_operand" "f"))
3470: (return)]
3471: "! TARGET_EPILOGUE"
3472: "ret\;fmovs %0,%%f0"
3473: [(set_attr "type" "multi")])
3474:
3475: ;; Now peepholes to go a call followed by a jump.
3476:
3477: (define_peephole
3478: [(parallel [(set (match_operand 0 "" "")
3479: (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r"))
3480: (match_operand 2 "" "")))
3481: (clobber (reg:SI 15))])
3482: (set (pc) (label_ref (match_operand 3 "" "")))]
3483: "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
3484: "*
3485: {
3486: return \"call %a1,%2\;add %%o7,(%l3-.-4),%%o7\";
3487: }")
3488:
3489: (define_peephole
3490: [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r"))
3491: (match_operand 1 "" ""))
3492: (clobber (reg:SI 15))])
3493: (set (pc) (label_ref (match_operand 2 "" "")))]
3494: "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
3495: "*
3496: {
3497: return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
3498: }")
3499:
3500: (define_peephole
3501: [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
3502: (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
3503: (reg:SI 0)))
3504: (clobber (reg:CC 0))])
3505: (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]
3506: ""
3507: "subxcc %r1,0,%0")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.