|
|
1.1 root 1: ;;- Machine description for SPARC chip for GNU C compiler
2: ;; Copyright (C) 1988, 1989 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 1, 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: ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
25: ;;- updates for most instructions.
26:
27: ;;- Operand classes for the register allocator:
28:
29: ;; Compare instructions.
30: ;; This controls RTL generation and register allocation.
31:
32: ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
33:
34: (define_insn "cmpsi"
35: [(set (cc0)
36: (compare (match_operand:SI 0 "arith_operand" "r,rI")
37: (match_operand:SI 1 "arith_operand" "I,r")))]
38: ""
39: "*
40: {
41: if (! REG_P (operands[0]))
42: {
43: cc_status.flags |= CC_REVERSED;
44: return \"cmp %1,%0\";
45: }
46: return \"cmp %0,%1\";
47: }")
48:
49: (define_expand "cmpdf"
50: [(set (cc0)
51: (compare (match_operand:DF 0 "nonmemory_operand" "f,fG")
52: (match_operand:DF 1 "nonmemory_operand" "G,f")))]
53: ""
54: "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, DFmode, 32)));")
55:
56: (define_insn ""
57: [(set (cc0)
58: (compare (match_operand:DF 0 "nonmemory_operand" "f,fG")
59: (match_operand:DF 1 "nonmemory_operand" "G,f")))]
60: ""
61: "*
62: {
63: if (GET_CODE (operands[0]) == CONST_DOUBLE
64: || GET_CODE (operands[1]) == CONST_DOUBLE)
65: make_f0_contain_0 (2);
66:
67: cc_status.flags |= CC_IN_FCCR;
68: if (GET_CODE (operands[0]) == CONST_DOUBLE)
69: return \"fcmped %%f0,%1\;nop\";
70: if (GET_CODE (operands[1]) == CONST_DOUBLE)
71: return \"fcmped %0,%%f0\;nop\";
72: return \"fcmped %0,%1\;nop\";
73: }")
74:
75: (define_expand "cmpsf"
76: [(set (cc0)
77: (compare (match_operand:SF 0 "nonmemory_operand" "f,fG")
78: (match_operand:SF 1 "nonmemory_operand" "G,f")))]
79: ""
80: "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SFmode, 32)));")
81:
82: (define_insn ""
83: [(set (cc0)
84: (compare (match_operand:SF 0 "nonmemory_operand" "f,fG")
85: (match_operand:SF 1 "nonmemory_operand" "G,f")))]
86: ""
87: "*
88: {
89: if (GET_CODE (operands[0]) == CONST_DOUBLE
90: || GET_CODE (operands[1]) == CONST_DOUBLE)
91: make_f0_contain_0 (1);
92:
93: cc_status.flags |= CC_IN_FCCR;
94: if (GET_CODE (operands[0]) == CONST_DOUBLE)
95: return \"fcmpes %%f0,%1\;nop\";
96: if (GET_CODE (operands[1]) == CONST_DOUBLE)
97: return \"fcmpes %0,%%f0\;nop\";
98: return \"fcmpes %0,%1\;nop\";
99: }")
100:
101: ;; Put tstsi first among test insns so it matches a CONST_INT operand.
102:
103: (define_insn "tstsi"
104: [(set (cc0)
105: (match_operand:SI 0 "register_operand" "r"))]
106: ""
107: "tst %0")
108:
109: ;; Need this to take a general operand because cse can make
110: ;; a CONST which won't be in a register.
111: (define_insn ""
112: [(set (cc0)
113: (match_operand:SI 0 "immediate_operand" "i"))]
114: ""
115: "set %0,%%g1\;tst %%g1")
116:
117: ;; Optimize the case of following a reg-reg move with a test
118: ;; of reg just moved.
119:
120: (define_peephole
121: [(set (match_operand:SI 0 "register_operand" "=r")
122: (match_operand:SI 1 "register_operand" "r"))
123: (set (cc0) (match_operand:SI 2 "register_operand" "r"))]
124: "operands[2] == operands[0]
125: || operands[2] == operands[1]"
126: "orcc %1,%%g0,%0 ! 2-insn combine")
127:
128: ;; Optimize 5(6) insn sequence to 3(4) insns.
129: ;; These patterns could also optimize more complicated sets
130: ;; before conditional branches.
131:
132: ;; Turned off because (1) this case is rarely encounted
133: ;; (2) to be correct, more conditions must be checked
134: ;; (3) the conditions must be checked with rtx_equal_p, not ==
135: ;; (4) when branch scheduling is added to the compiler,
136: ;; this optimization will be performed by the branch scheduler
137: ;; Bottom line: it is not worth the trouble of fixing or
138: ;; maintaining it.
139:
140: ;(define_peephole
141: ; [(set (match_operand:SI 0 "register_operand" "=r")
142: ; (match_operand:SI 1 "general_operand" "g"))
143: ; (set (match_operand:SI 2 "register_operand" "=r")
144: ; (match_operand:SI 3 "reg_or_0_operand" "rJ"))
145: ; (set (cc0) (match_operand:SI 4 "register_operand" "r"))
146: ; (set (pc) (match_operand 5 "" ""))]
147: ; "GET_CODE (operands[5]) == IF_THEN_ELSE
148: ; && operands[0] != operands[3]
149: ; && ! reg_mentioned_p (operands[2], operands[1])
150: ; && (operands[4] == operands[0]
151: ; || operands[4] == operands[2]
152: ; || operands[4] == operands[3])"
153: ; "*
154: ;{
155: ; rtx xoperands[2];
156: ; int parity;
157: ; xoperands[0] = XEXP (operands[5], 0);
158: ; if (GET_CODE (XEXP (operands[5], 1)) == PC)
159: ; {
160: ; parity = 1;
161: ; xoperands[1] = XEXP (XEXP (operands[5], 2), 0);
162: ; }
163: ; else
164: ; {
165: ; parity = 0;
166: ; xoperands[1] = XEXP (XEXP (operands[5], 1), 0);
167: ; }
168: ;
169: ; if (operands[4] == operands[0])
170: ; {
171: ; /* Although the constraints for operands[1] permit a general
172: ; operand (and hence possibly a const_int), we know that
173: ; in this branch it cannot be a CONST_INT, since that would give
174: ; us a fixed condition, and those should have been optimized away. */
175: ; if (REG_P (operands[1]))
176: ; output_asm_insn (\"orcc %1,%%g0,%0 ! 3-insn reorder\", operands);
177: ; else if (GET_CODE (operands[1]) != MEM)
178: ; abort ();
179: ; else
180: ; {
181: ; if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
182: ; output_asm_insn (\"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;tst %0 ! 4-insn reorder\", operands);
183: ; else
184: ; output_asm_insn (\"ld %1,%0\;tst %0 ! 3.5-insn reorder\", operands);
185: ; }
186: ; XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 2);
187: ; XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 3);
188: ; }
189: ; else
190: ; {
191: ; output_asm_insn (\"orcc %3,%%g0,%2 ! 3-insn reorder\", operands);
192: ; }
193: ; if (parity)
194: ; return output_delayed_branch (\"b%N0 %l1\", xoperands, insn);
195: ; else
196: ; return output_delayed_branch (\"b%C0 %l1\", xoperands, insn);
197: ;}")
198:
199: ;; By default, operations don't set the condition codes.
200: ;; These patterns allow cc's to be set, while doing some work
201:
202: (define_insn ""
203: [(set (cc0)
204: (zero_extend:SI (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)))]
205: ""
206: "andcc %0,0xff,%%g0")
207:
208: (define_insn ""
209: [(set (cc0)
210: (plus:SI (match_operand:SI 0 "register_operand" "r%")
211: (match_operand:SI 1 "arith_operand" "rI")))]
212: ""
213: "addcc %0,%1,%%g0")
214:
215: (define_insn ""
216: [(set (cc0)
217: (plus:SI (match_operand:SI 0 "register_operand" "r%")
218: (match_operand:SI 1 "arith_operand" "rI")))
219: (set (match_operand:SI 2 "register_operand" "=r")
220: (plus:SI (match_dup 0) (match_dup 1)))]
221: ""
222: "addcc %0,%1,%2")
223:
224: (define_insn ""
225: [(set (cc0)
226: (minus:SI (match_operand:SI 0 "register_operand" "r")
227: (match_operand:SI 1 "arith_operand" "rI")))
228: (set (match_operand:SI 2 "register_operand" "=r")
229: (minus:SI (match_dup 0) (match_dup 1)))]
230: ""
231: "subcc %0,%1,%2")
232:
233: (define_insn ""
234: [(set (cc0)
235: (and:SI (match_operand:SI 0 "register_operand" "r%")
236: (match_operand:SI 1 "arith_operand" "rI")))]
237: ""
238: "andcc %0,%1,%%g0")
239:
240: (define_insn ""
241: [(set (cc0)
242: (and:SI (match_operand:SI 0 "register_operand" "r%")
243: (match_operand:SI 1 "arith_operand" "rI")))
244: (set (match_operand:SI 2 "register_operand" "=r")
245: (and:SI (match_dup 0) (match_dup 1)))]
246: ""
247: "andcc %0,%1,%2")
248:
249: (define_insn ""
250: [(set (cc0)
251: (and:SI (match_operand:SI 0 "register_operand" "r%")
252: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
253: ""
254: "andncc %0,%1,%%g0")
255:
256: (define_insn ""
257: [(set (cc0)
258: (and:SI (match_operand:SI 0 "register_operand" "r%")
259: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
260: (set (match_operand:SI 2 "register_operand" "=r")
261: (and:SI (match_dup 0) (not:SI (match_dup 1))))]
262: ""
263: "andncc %0,%1,%2")
264:
265: (define_insn ""
266: [(set (cc0)
267: (ior:SI (match_operand:SI 0 "register_operand" "r%")
268: (match_operand:SI 1 "arith_operand" "rI")))]
269: ""
270: "orcc %0,%1,%%g0")
271:
272: (define_insn ""
273: [(set (cc0)
274: (ior:SI (match_operand:SI 0 "register_operand" "r%")
275: (match_operand:SI 1 "arith_operand" "rI")))
276: (set (match_operand:SI 2 "register_operand" "=r")
277: (ior:SI (match_dup 0) (match_dup 1)))]
278: ""
279: "orcc %0,%1,%2")
280:
281: (define_insn ""
282: [(set (cc0)
283: (ior:SI (match_operand:SI 0 "register_operand" "r%")
284: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
285: ""
286: "orncc %0,%1,%%g0")
287:
288: (define_insn ""
289: [(set (cc0)
290: (ior:SI (match_operand:SI 0 "register_operand" "r%")
291: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
292: (set (match_operand:SI 2 "register_operand" "=r")
293: (ior:SI (match_dup 0) (not:SI (match_dup 1))))]
294: ""
295: "orncc %0,%1,%2")
296:
297: (define_insn ""
298: [(set (cc0)
299: (xor:SI (match_operand:SI 0 "register_operand" "r%")
300: (match_operand:SI 1 "arith_operand" "rI")))]
301: ""
302: "xorcc %0,%1,%%g0")
303:
304: (define_insn ""
305: [(set (cc0)
306: (xor:SI (match_operand:SI 0 "register_operand" "r%")
307: (match_operand:SI 1 "arith_operand" "rI")))
308: (set (match_operand:SI 2 "register_operand" "=r")
309: (xor:SI (match_dup 0) (match_dup 1)))]
310: ""
311: "xorcc %0,%1,%2")
312:
313: (define_insn ""
314: [(set (cc0)
315: (xor:SI (match_operand:SI 0 "register_operand" "r%")
316: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
317: ""
318: "xnorcc %0,%1,%%g0")
319:
320: (define_insn ""
321: [(set (cc0)
322: (xor:SI (match_operand:SI 0 "register_operand" "r%")
323: (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
324: (set (match_operand:SI 2 "register_operand" "=r")
325: (xor:SI (match_dup 0) (not:SI (match_dup 1))))]
326: ""
327: "xnorcc %0,%1,%2")
328:
329: (define_expand "tstdf"
330: [(set (cc0)
331: (match_operand:DF 0 "register_operand" "f"))]
332: ""
333: "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, DFmode, 32)));")
334:
335: (define_insn ""
336: [(set (cc0)
337: (match_operand:DF 0 "register_operand" "f"))]
338: ""
339: "*
340: {
341: make_f0_contain_0 (2);
342: cc_status.flags |= CC_IN_FCCR;
343: return \"fcmped %0,%%f0\;nop\";
344: }")
345:
346: (define_expand "tstsf"
347: [(set (cc0)
348: (match_operand:SF 0 "register_operand" "f"))]
349: ""
350: "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SFmode, 32)));")
351:
352: (define_insn ""
353: [(set (cc0)
354: (match_operand:SF 0 "register_operand" "f"))]
355: ""
356: "*
357: {
358: make_f0_contain_0 (1);
359: cc_status.flags |= CC_IN_FCCR;
360: return \"fcmpes %0,%%f0\;nop\";
361: }")
362:
363: ;; There are no logical links for the condition codes. This
364: ;; would not normally be a problem, but on the SPARC (and possibly
365: ;; other RISC machines), when argument passing, the insn which sets
366: ;; the condition code and the insn which uses the set condition code
367: ;; may not be performed adjacently (due to optimizations performed
368: ;; in combine.c). To make up for this, we emit insn patterns which
369: ;; cannot possibly be rearranged on us.
370: (define_expand "seq"
371: [(set (match_operand:SI 0 "general_operand" "=r")
372: (eq (cc0) (const_int 0)))]
373: ""
374: "gen_scc_insn (EQ, VOIDmode, operands); DONE;")
375:
376: (define_expand "sne"
377: [(set (match_operand:SI 0 "general_operand" "=r")
378: (ne (cc0) (const_int 0)))]
379: ""
380: "gen_scc_insn (NE, VOIDmode, operands); DONE;")
381:
382: (define_insn ""
383: [(set (match_operand:SI 0 "general_operand" "=r,r")
384: (match_operator 1 "eq_or_neq"
385: [(compare (match_operand:SI 2 "general_operand" "r,rI")
386: (match_operand:SI 3 "general_operand" "I,r"))
387: (const_int 0)]))]
388: ""
389: "*
390: {
391: CC_STATUS_INIT;
392: cc_status.value1 = operands[0];
393: if (! REG_P (operands[2]))
394: {
395: output_asm_insn (\"cmp %3,%2\", operands);
396: cc_status.flags |= CC_REVERSED;
397: }
398: else
399: output_asm_insn (\"cmp %2,%3\", operands);
400: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
401: }")
402:
403: (define_insn ""
404: [(set (match_operand:SI 0 "general_operand" "=r")
405: (match_operator 1 "eq_or_neq"
406: [(match_operand:SI 2 "general_operand" "r")
407: (const_int 0)]))]
408: ""
409: "*
410: {
411: CC_STATUS_INIT;
412: cc_status.value1 = operands[0];
413: output_asm_insn (\"tst %2\", operands);
414: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
415: }")
416:
417: (define_insn ""
418: [(set (match_operand:SI 0 "general_operand" "=r,r")
419: (match_operator 1 "eq_or_neq"
420: [(compare (match_operand:DF 2 "general_operand" "f,fG")
421: (match_operand:DF 3 "general_operand" "G,f"))
422: (const_int 0)]))]
423: ""
424: "*
425: {
426: CC_STATUS_INIT;
427: cc_status.value1 = operands[0];
428: cc_status.flags |= CC_IN_FCCR;
429:
430: if (GET_CODE (operands[2]) == CONST_DOUBLE
431: || GET_CODE (operands[3]) == CONST_DOUBLE)
432: make_f0_contain_0 (2);
433:
434: if (GET_CODE (operands[2]) == CONST_DOUBLE)
435: output_asm_insn (\"fcmped %%f0,%3\;nop\", operands);
436: else if (GET_CODE (operands[3]) == CONST_DOUBLE)
437: output_asm_insn (\"fcmped %2,%%f0\;nop\", operands);
438: else output_asm_insn (\"fcmped %2,%3\;nop\", operands);
439: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
440: }")
441:
442: (define_insn ""
443: [(set (match_operand:SI 0 "general_operand" "=r")
444: (match_operator 1 "eq_or_neq"
445: [(match_operand:DF 2 "general_operand" "f")
446: (const_int 0)]))]
447: ""
448: "*
449: {
450: CC_STATUS_INIT;
451: cc_status.value1 = operands[0];
452: cc_status.flags |= CC_IN_FCCR;
453:
454: make_f0_contain_0 (2);
455: output_asm_insn (\"fcmped %2,%%f0\;nop\", operands);
456: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
457: }")
458:
459: (define_insn ""
460: [(set (match_operand:SI 0 "general_operand" "=r,r")
461: (match_operator 1 "eq_or_neq"
462: [(compare (match_operand:SF 2 "general_operand" "f,fG")
463: (match_operand:SF 3 "general_operand" "G,f"))
464: (const_int 0)]))]
465: ""
466: "*
467: {
468: CC_STATUS_INIT;
469: cc_status.value1 = operands[0];
470: cc_status.flags |= CC_IN_FCCR;
471:
472: if (GET_CODE (operands[2]) == CONST_DOUBLE
473: || GET_CODE (operands[3]) == CONST_DOUBLE)
474: make_f0_contain_0 (1);
475:
476: if (GET_CODE (operands[2]) == CONST_DOUBLE)
477: output_asm_insn (\"fcmpes %%f0,%3\;nop\", operands);
478: else if (GET_CODE (operands[3]) == CONST_DOUBLE)
479: output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands);
480: else output_asm_insn (\"fcmpes %2,%3\;nop\", operands);
481: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
482: }")
483:
484: (define_insn ""
485: [(set (match_operand:SI 0 "general_operand" "=r")
486: (match_operator 1 "eq_or_neq"
487: [(match_operand:SF 2 "general_operand" "f")
488: (const_int 0)]))]
489: ""
490: "*
491: {
492: CC_STATUS_INIT;
493: cc_status.value1 = operands[0];
494: cc_status.flags |= CC_IN_FCCR;
495:
496: make_f0_contain_0 (1);
497: output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands);
498: return output_scc_insn (GET_CODE (operands[1]), operands[0]);
499: }")
500:
501: ;; These control RTL generation for conditional jump insns
502: ;; and match them for register allocation.
503:
504: (define_insn "beq"
505: [(set (pc)
506: (if_then_else (eq (cc0)
507: (const_int 0))
508: (label_ref (match_operand 0 "" ""))
509: (pc)))]
510: ""
511: "*
512: {
513: if (cc_prev_status.flags & CC_IN_FCCR)
514: return \"fbe %l0\;nop\";
515: return \"be %l0\;nop\";
516: }")
517:
518: (define_insn "bne"
519: [(set (pc)
520: (if_then_else (ne (cc0)
521: (const_int 0))
522: (label_ref (match_operand 0 "" ""))
523: (pc)))]
524: ""
525: "*
526: {
527: if (cc_prev_status.flags & CC_IN_FCCR)
528: return \"fbne %l0\;nop\";
529: return \"bne %l0\;nop\";
530: }")
531:
532: (define_insn "bgt"
533: [(set (pc)
534: (if_then_else (gt (cc0)
535: (const_int 0))
536: (label_ref (match_operand 0 "" ""))
537: (pc)))]
538: ""
539: "*
540: {
541: if (cc_prev_status.flags & CC_IN_FCCR)
542: return \"fbg %l0\;nop\";
543: return \"bg %l0\;nop\";
544: }")
545:
546: (define_insn "bgtu"
547: [(set (pc)
548: (if_then_else (gtu (cc0)
549: (const_int 0))
550: (label_ref (match_operand 0 "" ""))
551: (pc)))]
552: ""
553: "*
554: {
555: if (cc_prev_status.flags & CC_IN_FCCR)
556: abort ();
557: return \"bgu %l0\;nop\";
558: }")
559:
560: (define_insn "blt"
561: [(set (pc)
562: (if_then_else (lt (cc0)
563: (const_int 0))
564: (label_ref (match_operand 0 "" ""))
565: (pc)))]
566: ""
567: "*
568: {
569: if (cc_prev_status.flags & CC_IN_FCCR)
570: return \"fbl %l0\;nop\";
571: return \"bl %l0\;nop\";
572: }")
573:
574: (define_insn "bltu"
575: [(set (pc)
576: (if_then_else (ltu (cc0)
577: (const_int 0))
578: (label_ref (match_operand 0 "" ""))
579: (pc)))]
580: ""
581: "*
582: {
583: if (cc_prev_status.flags & CC_IN_FCCR)
584: abort ();
585: return \"blu %l0\;nop\";
586: }")
587:
588: (define_insn "bge"
589: [(set (pc)
590: (if_then_else (ge (cc0)
591: (const_int 0))
592: (label_ref (match_operand 0 "" ""))
593: (pc)))]
594: ""
595: "*
596: {
597: if (cc_prev_status.flags & CC_IN_FCCR)
598: return \"fbge %l0\;nop\";
599: return \"bge %l0\;nop\";
600: }")
601:
602: (define_insn "bgeu"
603: [(set (pc)
604: (if_then_else (geu (cc0)
605: (const_int 0))
606: (label_ref (match_operand 0 "" ""))
607: (pc)))]
608: ""
609: "*
610: {
611: if (cc_prev_status.flags & CC_IN_FCCR)
612: abort ();
613: return \"bgeu %l0\;nop\";
614: }")
615:
616: (define_insn "ble"
617: [(set (pc)
618: (if_then_else (le (cc0)
619: (const_int 0))
620: (label_ref (match_operand 0 "" ""))
621: (pc)))]
622: ""
623: "*
624: {
625: if (cc_prev_status.flags & CC_IN_FCCR)
626: return \"fble %l0\;nop\";
627: return \"ble %l0\;nop\";
628: }")
629:
630: (define_insn "bleu"
631: [(set (pc)
632: (if_then_else (leu (cc0)
633: (const_int 0))
634: (label_ref (match_operand 0 "" ""))
635: (pc)))]
636: ""
637: "*
638: {
639: if (cc_prev_status.flags & CC_IN_FCCR)
640: abort ();
641: return \"bleu %l0\;nop\";
642: }")
643:
644: ;; This matches inverted jump insns for register allocation.
645:
646: (define_insn ""
647: [(set (pc)
648: (if_then_else (match_operator 0 "relop" [(cc0) (const_int 0)])
649: (pc)
650: (label_ref (match_operand 1 "" ""))))]
651: ""
652: "*
653: {
654: if (cc_prev_status.flags & CC_IN_FCCR)
655: return \"fb%F0 %l1\;nop\";
656: return \"b%N0 %l1\;nop\";
657: }")
658:
659: ;; Move instructions
660:
661: (define_insn "swapsi"
662: [(set (match_operand:SI 0 "general_operand" "r,rm")
663: (match_operand:SI 1 "general_operand" "m,r"))
664: (set (match_dup 1) (match_dup 0))]
665: ""
666: "*
667: {
668: if (GET_CODE (operands[1]) == MEM)
669: {
670: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
671: output_asm_insn (\"set %a1,%%g1\", operands),
672: operands[1] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 1)),
673: cc_status.flags &= ~CC_KNOW_HI_G1;
674: output_asm_insn (\"swap %1,%0\", operands);
675: }
676: if (REG_P (operands[0]))
677: {
678: if (REGNO (operands[0]) == REGNO (operands[1]))
679: return \"\";
680: return \"xor %0,%1,%0\;xor %1,%0,%1\;xor %0,%1,%0\";
681: }
682: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
683: {
684: output_asm_insn (\"set %a0,%%g1\", operands);
685: operands[0] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 1));
686: cc_status.flags &= ~CC_KNOW_HI_G1;
687: }
688: return \"swap %0,%1\";
689: }")
690:
691: (define_insn "movsi"
692: [(set (match_operand:SI 0 "general_operand" "=r,m")
693: (match_operand:SI 1 "general_operand" "rmif,rJ"))]
694: ""
695: "*
696: {
697: if (GET_CODE (operands[0]) == MEM)
698: {
699: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
700: return output_store (operands);
701: return \"st %r1,%0\";
702: }
703: if (GET_CODE (operands[1]) == MEM)
704: {
705: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
706: return output_load_fixed (operands);
707: return \"ld %1,%0\";
708: }
709: if (FP_REG_P (operands[1]))
710: return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
711: if (REG_P (operands[1])
712: || (GET_CODE (operands[1]) == CONST_INT
713: && SMALL_INT (operands[1])))
714: return \"mov %1,%0\";
715: if (GET_CODE (operands[1]) == CONST_INT
716: && (INTVAL (operands[1]) & 0x3ff) == 0)
717: return \"sethi %%hi(%1),%0\";
718: return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
719: }")
720:
721: (define_insn "movhi"
722: [(set (match_operand:HI 0 "general_operand" "=r,m")
723: (match_operand:HI 1 "general_operand" "rmi,rJ"))]
724: ""
725: "*
726: {
727: if (GET_CODE (operands[0]) == MEM)
728: {
729: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
730: return output_store (operands);
731: return \"sth %r1,%0\";
732: }
733: if (GET_CODE (operands[1]) == MEM)
734: {
735: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
736: return output_load_fixed (operands);
737: return \"ldsh %1,%0\";
738: }
739: if (REG_P (operands[1])
740: || (GET_CODE (operands[1]) == CONST_INT
741: && SMALL_INT (operands[1])))
742: return \"mov %1,%0\";
743: return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
744: }")
745:
746: (define_insn "movqi"
747: [(set (match_operand:QI 0 "general_operand" "=r,m")
748: (match_operand:QI 1 "general_operand" "rmi,rJ"))]
749: ""
750: "*
751: {
752: if (GET_CODE (operands[0]) == MEM)
753: {
754: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
755: return output_store (operands);
756: return \"stb %r1,%0\";
757: }
758: if (GET_CODE (operands[1]) == MEM)
759: {
760: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
761: return output_load_fixed (operands);
762: return \"ldsb %1,%0\";
763: }
764: if (REG_P (operands[1])
765: || (GET_CODE (operands[1]) == CONST_INT
766: && SMALL_INT (operands[1])))
767: return \"mov %1,%0\";
768: return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
769: }")
770:
771: ;; The definition of this insn does not really explain what it does,
772: ;; but it should suffice
773: ;; that anything generated as this insn will be recognized as one
774: ;; and that it won't successfully combine with anything.
775: (define_expand "movstrsi"
776: [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
777: (mem:BLK (match_operand:BLK 1 "general_operand" "")))
778: (use (match_operand:SI 2 "arith32_operand" ""))
779: (use (match_operand:SI 3 "immediate_operand" ""))
780: (clobber (match_dup 4))
781: (clobber (match_dup 0))
782: (clobber (match_dup 1))])]
783: ""
784: "
785: {
786: operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
787: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
788: operands[4] = gen_reg_rtx (SImode);
789: }")
790:
791: (define_insn ""
792: [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
793: (mem:BLK (match_operand:SI 1 "register_operand" "r")))
794: (use (match_operand:SI 2 "arith32_operand" "rn"))
795: (use (match_operand:SI 3 "immediate_operand" "i"))
796: (clobber (match_operand:SI 4 "register_operand" "=r"))
797: (clobber (match_operand:SI 5 "register_operand" "=0"))
798: (clobber (match_operand:SI 6 "register_operand" "=1"))]
799: ""
800: "* return output_block_move (operands);")
801:
802: ;; Floating point move insns
803:
804: ;; This pattern forces (set (reg:DF ...) (const_double ...))
805: ;; to be reloaded by putting the constant into memory.
806: ;; It must come before the more general movdf pattern.
807: (define_insn ""
808: [(set (match_operand:DF 0 "general_operand" "=r,f,o")
809: (match_operand:DF 1 "" "mG,m,G"))]
810: "GET_CODE (operands[1]) == CONST_DOUBLE"
811: "*
812: {
813: if (FP_REG_P (operands[0]))
814: return output_fp_move_double (operands);
815: if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
816: {
817: operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
818: return \"mov %%g0,%0\;mov %%g0,%1\";
819: }
820: if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
821: {
822: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
823: {
824: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
825: && XEXP (operands[0], 0) == cc_prev_status.mdep))
826: {
827: cc_status.flags |= CC_KNOW_HI_G1;
828: cc_status.mdep = XEXP (operands[0], 0);
829: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
830: }
831: return \"st %%g0,[%%g1+%%lo(%%m0)]\;st %%g0,[%%g1+%%lo(%%m0)+4]\";
832: }
833: operands[1] = adj_offsettable_operand (operands[0], 4);
834: return \"st %%g0,%0\;st %%g0,%1\";
835: }
836: return output_move_double (operands);
837: }")
838:
839: (define_insn "movdf"
840: [(set (match_operand:DF 0 "general_operand" "=rm,&r,?f,?rm")
841: (match_operand:DF 1 "general_operand" "r,m,rfm,f"))]
842: ""
843: "*
844: {
845: if (GET_CODE (operands[0]) == MEM
846: && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
847: return output_store (operands);
848: if (GET_CODE (operands[1]) == MEM
849: && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
850: return output_load_floating (operands);
851:
852: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
853: return output_fp_move_double (operands);
854: return output_move_double (operands);
855: }")
856:
857: (define_insn "movdi"
858: [(set (match_operand:DI 0 "general_operand" "=rm,&r,?f,?rm")
859: (match_operand:DI 1 "general_operand" "r,mi,rfm,f"))]
860: ""
861: "*
862: {
863: if (GET_CODE (operands[0]) == MEM
864: && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
865: return output_store (operands);
866: if (GET_CODE (operands[1]) == MEM
867: && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
868: return output_load_fixed (operands);
869:
870: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
871: return output_fp_move_double (operands);
872: return output_move_double (operands);
873: }")
874:
875: (define_insn "movsf"
876: [(set (match_operand:SF 0 "general_operand" "=rf,m")
877: (match_operand:SF 1 "general_operand" "rfm,rf"))]
878: ""
879: "*
880: {
881: if (GET_CODE (operands[0]) == MEM
882: && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
883: return output_store (operands);
884: if (GET_CODE (operands[1]) == MEM
885: && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
886: return output_load_floating (operands);
887: if (FP_REG_P (operands[0]))
888: {
889: if (FP_REG_P (operands[1]))
890: return \"fmovs %1,%0\";
891: if (GET_CODE (operands[1]) == REG)
892: return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
893: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
894: {
895: cc_status.flags |= CC_KNOW_HI_G1;
896: cc_status.mdep = XEXP (operands[1], 0);
897: return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\";
898: }
899: return \"ld %1,%0\";
900: }
901: if (FP_REG_P (operands[1]))
902: {
903: if (GET_CODE (operands[0]) == REG)
904: return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
905: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
906: {
907: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
908: && XEXP (operands[0], 0) == cc_prev_status.mdep))
909: {
910: cc_status.flags |= CC_KNOW_HI_G1;
911: cc_status.mdep = XEXP (operands[0], 0);
912: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
913: }
914: return \"st %r1,[%%g1+%%lo(%m0)]\";
915: }
916: return \"st %r1,%0\";
917: }
918: if (GET_CODE (operands[0]) == MEM)
919: return \"st %r1,%0\";
920: if (GET_CODE (operands[1]) == MEM)
921: return \"ld %1,%0\";
922: return \"mov %1,%0\";
923: }")
924:
925: ;;- truncation instructions
926: (define_insn "truncsiqi2"
927: [(set (match_operand:QI 0 "general_operand" "=g")
928: (truncate:QI
929: (match_operand:SI 1 "register_operand" "r")))]
930: ""
931: "*
932: {
933: if (GET_CODE (operands[0]) == MEM)
934: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
935: {
936: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
937: && XEXP (operands[0], 0) == cc_prev_status.mdep))
938: {
939: cc_status.flags |= CC_KNOW_HI_G1;
940: cc_status.mdep = XEXP (operands[0], 0);
941: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
942: }
943: return \"stb %1,[%%g1+%%lo(%m0)]\";
944: }
945: else
946: return \"stb %1,%0\";
947: return \"mov %1,%0\";
948: }")
949:
950: (define_insn "trunchiqi2"
951: [(set (match_operand:QI 0 "general_operand" "=g")
952: (truncate:QI
953: (match_operand:HI 1 "register_operand" "r")))]
954: ""
955: "*
956: {
957: if (GET_CODE (operands[0]) == MEM)
958: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
959: {
960: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
961: && XEXP (operands[0], 0) == cc_prev_status.mdep))
962: {
963: cc_status.flags |= CC_KNOW_HI_G1;
964: cc_status.mdep = XEXP (operands[0], 0);
965: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
966: }
967: return \"stb %1,[%%g1+%%lo(%m0)]\";
968: }
969: else
970: return \"stb %1,%0\";
971: return \"mov %1,%0\";
972: }")
973:
974: (define_insn "truncsihi2"
975: [(set (match_operand:HI 0 "general_operand" "=g")
976: (truncate:HI
977: (match_operand:SI 1 "register_operand" "r")))]
978: ""
979: "*
980: {
981: if (GET_CODE (operands[0]) == MEM)
982: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
983: {
984: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
985: && XEXP (operands[0], 0) == cc_prev_status.mdep))
986: {
987: cc_status.flags |= CC_KNOW_HI_G1;
988: cc_status.mdep = XEXP (operands[0], 0);
989: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
990: }
991: return \"sth %1,[%%g1+%%lo(%m0)]\";
992: }
993: else
994: return \"sth %1,%0\";
995: return \"mov %1,%0\";
996: }")
997:
998: ;;- zero extension instructions
999:
1000: ;; Note that the one starting from HImode comes before those for QImode
1001: ;; so that a constant operand will match HImode, not QImode.
1002:
1003: (define_insn "zero_extendhisi2"
1004: [(set (match_operand:SI 0 "register_operand" "=r")
1005: (zero_extend:SI
1006: (match_operand:HI 1 "general_operand" "g")))]
1007: ""
1008: "*
1009: {
1010: if (REG_P (operands[1]))
1011: return \"sll %1,0x10,%0\;srl %0,0x10,%0\";
1012: if (GET_CODE (operands[1]) == CONST_INT)
1013: abort ();
1014: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1015: {
1016: cc_status.flags |= CC_KNOW_HI_G1;
1017: cc_status.mdep = XEXP (operands[1], 0);
1018: return \"sethi %%hi(%m1),%%g1\;lduh [%%g1+%%lo(%m1)],%0\";
1019: }
1020: else
1021: return \"lduh %1,%0\";
1022: }")
1023:
1024: (define_insn "zero_extendqihi2"
1025: [(set (match_operand:HI 0 "register_operand" "=r")
1026: (zero_extend:HI
1027: (match_operand:QI 1 "general_operand" "g")))]
1028: ""
1029: "*
1030: {
1031: if (REG_P (operands[1]))
1032: return \"and %1,0xff,%0\";
1033: if (GET_CODE (operands[1]) == CONST_INT)
1034: abort ();
1035: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1036: {
1037: cc_status.flags |= CC_KNOW_HI_G1;
1038: cc_status.mdep = XEXP (operands[1], 0);
1039: return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
1040: }
1041: else
1042: return \"ldub %1,%0\";
1043: }")
1044:
1045: (define_insn "zero_extendqisi2"
1046: [(set (match_operand:SI 0 "register_operand" "=r")
1047: (zero_extend:SI
1048: (match_operand:QI 1 "general_operand" "g")))]
1049: ""
1050: "*
1051: {
1052: if (REG_P (operands[1]))
1053: return \"and %1,0xff,%0\";
1054: if (GET_CODE (operands[1]) == CONST_INT)
1055: abort ();
1056: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1057: {
1058: cc_status.flags |= CC_KNOW_HI_G1;
1059: cc_status.mdep = XEXP (operands[1], 0);
1060: return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
1061: }
1062: else
1063: return \"ldub %1,%0\";
1064: }")
1065:
1066: ;;- sign extension instructions
1067: ;; Note that the one starting from HImode comes before those for QImode
1068: ;; so that a constant operand will match HImode, not QImode.
1069:
1070: (define_insn "extendhisi2"
1071: [(set (match_operand:SI 0 "register_operand" "=r")
1072: (sign_extend:SI
1073: (match_operand:HI 1 "general_operand" "g")))]
1074: ""
1075: "*
1076: {
1077: if (REG_P (operands[1]))
1078: return \"sll %1,0x10,%0\;sra %0,0x10,%0\";
1079: if (GET_CODE (operands[1]) == CONST_INT)
1080: abort ();
1081: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1082: {
1083: cc_status.flags |= CC_KNOW_HI_G1;
1084: cc_status.mdep = XEXP (operands[1], 0);
1085: return \"sethi %%hi(%m1),%%g1\;ldsh [%%g1+%%lo(%m1)],%0\";
1086: }
1087: else
1088: return \"ldsh %1,%0\";
1089: }")
1090:
1091: (define_insn "extendqihi2"
1092: [(set (match_operand:HI 0 "register_operand" "=r")
1093: (sign_extend:HI
1094: (match_operand:QI 1 "general_operand" "g")))]
1095: ""
1096: "*
1097: {
1098: if (REG_P (operands[1]))
1099: return \"sll %1,0x18,%0\;sra %0,0x18,%0\";
1100: if (GET_CODE (operands[1]) == CONST_INT)
1101: abort ();
1102: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1103: {
1104: cc_status.flags |= CC_KNOW_HI_G1;
1105: cc_status.mdep = XEXP (operands[1], 0);
1106: return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
1107: }
1108: else
1109: return \"ldsb %1,%0\";
1110: }")
1111:
1112: (define_insn "extendqisi2"
1113: [(set (match_operand:SI 0 "register_operand" "=r")
1114: (sign_extend:SI
1115: (match_operand:QI 1 "general_operand" "g")))]
1116: ""
1117: "*
1118: {
1119: if (REG_P (operands[1]))
1120: return \"sll %1,0x18,%0\;sra %0,0x18,%0\";
1121: if (GET_CODE (operands[1]) == CONST_INT)
1122: abort ();
1123: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1124: {
1125: cc_status.flags |= CC_KNOW_HI_G1;
1126: cc_status.mdep = XEXP (operands[1], 0);
1127: return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
1128: }
1129: else
1130: return \"ldsb %1,%0\";
1131: }")
1132:
1133: ;; Signed bitfield extractions come out looking like
1134: ;; (shiftrt (shift (sign_extend <Y>) <C1>) <C2>)
1135: ;; which we expand poorly as four shift insns.
1136: ;; These patters yeild two shifts:
1137: ;; (shiftrt (shift <Y> <C3>) <C4>)
1138: (define_insn ""
1139: [(set (match_operand:SI 0 "register_operand" "=r")
1140: (ashiftrt:SI
1141: (sign_extend:SI
1142: (match_operand:QI 1 "register_operand" "r"))
1143: (match_operand:SI 2 "small_int" "n")))]
1144: ""
1145: "sll %1,0x18,%0\;sra %0,0x18+%2,%0")
1146:
1147: (define_insn ""
1148: [(set (match_operand:SI 0 "register_operand" "=r")
1149: (ashiftrt:SI
1150: (sign_extend:SI
1151: (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r")
1152: (match_operand:SI 2 "small_int" "n")) 0))
1153: (match_operand:SI 3 "small_int" "n")))]
1154: ""
1155: "sll %1,0x18+%2,%0\;sra %0,0x18+%3,%0")
1156:
1157: ;; Special patterns for optimizing bit-field instructions.
1158:
1159: ;; First two patterns are for bitfields that came from memory
1160: ;; testing only the high bit. They work with old combiner.
1161: ;; @@ Actually, the second pattern does not work if we
1162: ;; @@ need to set the N bit.
1163: (define_insn ""
1164: [(set (cc0)
1165: (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
1166: (const_int 7)) 0)))]
1167: "0"
1168: "andcc %0,128,%%g0")
1169:
1170: (define_insn ""
1171: [(set (cc0)
1172: (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
1173: (const_int 7)) 0)))]
1174: "0"
1175: "andcc %0,128,%%g0")
1176:
1177: ;; next two patterns are good for bitfields coming from memory
1178: ;; (via pseudo-register) or from a register, though this optimization
1179: ;; is only good for values contained wholly within the bottom 13 bits
1180: (define_insn ""
1181: [(set (cc0)
1182: (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
1183: (match_operand:SI 1 "small_int" "n"))
1184: (match_operand:SI 2 "small_int" "n")))]
1185: "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000"
1186: "andcc %0,%2<<%1,%%g0")
1187:
1188: (define_insn ""
1189: [(set (cc0)
1190: (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
1191: (match_operand:SI 1 "small_int" "n"))
1192: (match_operand:SI 2 "small_int" "n")))]
1193: "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000"
1194: "andcc %0,%2<<%1,%%g0")
1195:
1196: ;; Conversions between float and double.
1197:
1198: (define_insn "extendsfdf2"
1199: [(set (match_operand:DF 0 "register_operand" "=f")
1200: (float_extend:DF
1201: (match_operand:SF 1 "register_operand" "f")))]
1202: ""
1203: "fstod %1,%0")
1204:
1205: (define_insn "truncdfsf2"
1206: [(set (match_operand:SF 0 "register_operand" "=f")
1207: (float_truncate:SF
1208: (match_operand:DF 1 "register_operand" "f")))]
1209: ""
1210: "fdtos %1,%0")
1211:
1212: ;; Conversion between fixed point and floating point.
1213: ;; Note that among the fix-to-float insns
1214: ;; the ones that start with SImode come first.
1215: ;; That is so that an operand that is a CONST_INT
1216: ;; (and therefore lacks a specific machine mode).
1217: ;; will be recognized as SImode (which is always valid)
1218: ;; rather than as QImode or HImode.
1219:
1220: ;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...)))
1221: ;; to be reloaded by putting the constant into memory.
1222: ;; It must come before the more general floatsisf2 pattern.
1223: (define_insn ""
1224: [(set (match_operand:SF 0 "general_operand" "=f")
1225: (float:SF (match_operand 1 "" "m")))]
1226: "GET_CODE (operands[1]) == CONST_INT"
1227: "*
1228: {
1229: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1230: {
1231: cc_status.flags |= CC_KNOW_HI_G1;
1232: cc_status.mdep = XEXP (operands[1], 0);
1233: return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\";
1234: }
1235: return \"ld %1,%0\;fitos %0,%0\";
1236: }")
1237:
1238: (define_insn "floatsisf2"
1239: [(set (match_operand:SF 0 "general_operand" "=f")
1240: (float:SF (match_operand:SI 1 "general_operand" "rfm")))]
1241: ""
1242: "*
1243: {
1244: if (GET_CODE (operands[1]) == MEM)
1245: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1246: {
1247: cc_status.flags |= CC_KNOW_HI_G1;
1248: cc_status.mdep = XEXP (operands[1], 0);
1249: return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\";
1250: }
1251: else
1252: return \"ld %1,%0\;fitos %0,%0\";
1253: else if (FP_REG_P (operands[1]))
1254: return \"fitos %1,%0\";
1255: return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitos %0,%0\";
1256: }")
1257:
1258: ;; This pattern forces (set (reg:DF ...) (float:DF (const_int ...)))
1259: ;; to be reloaded by putting the constant into memory.
1260: ;; It must come before the more general floatsidf2 pattern.
1261: (define_insn ""
1262: [(set (match_operand:DF 0 "general_operand" "=f")
1263: (float:DF (match_operand 1 "" "m")))]
1264: "GET_CODE (operands[1]) == CONST_INT"
1265: "*
1266: {
1267: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1268: {
1269: cc_status.flags |= CC_KNOW_HI_G1;
1270: cc_status.mdep = XEXP (operands[1], 0);
1271: return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\";
1272: }
1273: return \"ld %1,%0\;fitod %0,%0\";
1274: }")
1275:
1276: (define_insn "floatsidf2"
1277: [(set (match_operand:DF 0 "general_operand" "=f")
1278: (float:DF (match_operand:SI 1 "general_operand" "rfm")))]
1279: ""
1280: "*
1281: {
1282: if (GET_CODE (operands[1]) == MEM)
1283: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1284: {
1285: cc_status.flags |= CC_KNOW_HI_G1;
1286: cc_status.mdep = XEXP (operands[1], 0);
1287: return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\";
1288: }
1289: else
1290: return \"ld %1,%0\;fitod %0,%0\";
1291: else if (FP_REG_P (operands[1]))
1292: return \"fitod %1,%0\";
1293: else
1294: return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitod %0,%0\";
1295: }")
1296:
1297: ;; Convert a float to an actual integer.
1298: ;; Truncation is performed as part of the conversion.
1299: (define_insn "fix_truncsfsi2"
1300: [(set (match_operand:SI 0 "general_operand" "=rm")
1301: (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
1302: ""
1303: "*
1304: {
1305: cc_status.flags &= ~(CC_F1_IS_0);
1306: if (FP_REG_P (operands[1]))
1307: output_asm_insn (\"fstoi %1,%%f1\", operands);
1308: else if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1309: {
1310: cc_status.flags |= CC_KNOW_HI_G1;
1311: cc_status.mdep = XEXP (operands[1], 0);
1312: output_asm_insn (\"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%%f1\;fstoi %%f1,%%f1\", operands);
1313: }
1314: else
1315: output_asm_insn (\"ld %1,%%f1\;fstoi %%f1,%%f1\", operands);
1316: if (GET_CODE (operands[0]) == MEM)
1317: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1318: {
1319: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
1320: && XEXP (operands[0], 0) == cc_prev_status.mdep))
1321: {
1322: cc_status.flags |= CC_KNOW_HI_G1;
1323: cc_status.mdep = XEXP (operands[0], 0);
1324: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
1325: }
1326: return \"st %%f1,[%%g1+%%lo(%m0)]\";
1327: }
1328: else
1329: return \"st %%f1,%0\";
1330: else
1331: return \"st %%f1,[%%fp-4]\;ld [%%fp-4],%0\";
1332: }")
1333:
1334: (define_insn "fix_truncdfsi2"
1335: [(set (match_operand:SI 0 "general_operand" "=rm")
1336: (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
1337: ""
1338: "*
1339: {
1340: cc_status.flags &= ~CC_F0_IS_0;
1341: if (FP_REG_P (operands[1]))
1342: output_asm_insn (\"fdtoi %1,%%f0\", operands);
1343: else
1344: {
1345: rtx xoperands[2];
1346: xoperands[0] = gen_rtx (REG, DFmode, 32);
1347: xoperands[1] = operands[1];
1348: output_asm_insn (output_fp_move_double (xoperands), xoperands);
1349: output_asm_insn (\"fdtoi %%f0,%%f0\", 0);
1350: }
1351: if (GET_CODE (operands[0]) == MEM)
1352: if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1353: {
1354: if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
1355: && XEXP (operands[0], 0) == cc_prev_status.mdep))
1356: {
1357: cc_status.flags |= CC_KNOW_HI_G1;
1358: cc_status.mdep = XEXP (operands[0], 0);
1359: output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
1360: }
1361: return \"st %%f0,[%%g1+%%lo(%m0)]\";
1362: }
1363: else
1364: return \"st %%f0,%0\";
1365: else
1366: return \"st %%f0,[%%fp-4]\;ld [%%fp-4],%0\";
1367: }")
1368:
1369: ;;- arithmetic instructions
1370:
1371: (define_insn "addsi3"
1372: [(set (match_operand:SI 0 "register_operand" "=r")
1373: (plus:SI (match_operand:SI 1 "arith32_operand" "%r")
1374: (match_operand:SI 2 "arith32_operand" "rn")))]
1375: ""
1376: "*
1377: {
1378: if (REG_P (operands[2]))
1379: return \"add %1,%2,%0\";
1380: if (SMALL_INT (operands[2]))
1381: return \"add %1,%2,%0\";
1382: cc_status.flags &= ~CC_KNOW_HI_G1;
1383: return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;add %1,%%g1,%0\";
1384: }")
1385:
1386: (define_insn "subsi3"
1387: [(set (match_operand:SI 0 "register_operand" "=r")
1388: (minus:SI (match_operand:SI 1 "register_operand" "r")
1389: (match_operand:SI 2 "arith32_operand" "rn")))]
1390: ""
1391: "*
1392: {
1393: if (REG_P (operands[2]))
1394: return \"sub %1,%2,%0\";
1395: if (SMALL_INT (operands[2]))
1396: return \"sub %1,%2,%0\";
1397: cc_status.flags &= ~CC_KNOW_HI_G1;
1398: return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;sub %1,%%g1,%0\";
1399: }")
1400:
1401: (define_expand "mulsi3"
1402: [(set (match_operand:SI 0 "register_operand" "r")
1403: (mult:SI (match_operand:SI 1 "general_operand" "")
1404: (match_operand:SI 2 "general_operand" "")))]
1405: ""
1406: "
1407: {
1408: rtx src;
1409:
1410: if (GET_CODE (operands[1]) == CONST_INT)
1411: if (GET_CODE (operands[2]) == CONST_INT)
1412: {
1413: emit_move_insn (operands[0],
1414: gen_rtx (CONST_INT, VOIDmode,
1415: INTVAL (operands[1]) * INTVAL (operands[2])));
1416: DONE;
1417: }
1418: else
1419: src = gen_rtx (MULT, SImode,
1420: copy_to_mode_reg (SImode, operands[2]),
1421: operands[1]);
1422: else if (GET_CODE (operands[2]) == CONST_INT)
1423: src = gen_rtx (MULT, SImode,
1424: copy_to_mode_reg (SImode, operands[1]),
1425: operands[2]);
1426: else src = 0;
1427:
1428: if (src)
1429: emit_insn (gen_rtx (SET, VOIDmode, operands[0], src));
1430: else
1431: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
1432: gen_rtx (SET, VOIDmode, operands[0],
1433: gen_rtx (MULT, SImode, operands[1], operands[2])),
1434: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 8)),
1435: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 9)),
1436: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 12)),
1437: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 13)))));
1438: DONE;
1439: }")
1440:
1441: (define_expand "umulsi3"
1442: [(set (match_operand:SI 0 "register_operand" "r")
1443: (umult:SI (match_operand:SI 1 "general_operand" "")
1444: (match_operand:SI 2 "general_operand" "")))]
1445: ""
1446: "
1447: {
1448: rtx src;
1449:
1450: if (GET_CODE (operands[1]) == CONST_INT)
1451: if (GET_CODE (operands[2]) == CONST_INT)
1452: {
1453: emit_move_insn (operands[0],
1454: gen_rtx (CONST_INT, VOIDmode,
1455: (unsigned)INTVAL (operands[1]) * (unsigned)INTVAL (operands[2])));
1456: DONE;
1457: }
1458: else
1459: src = gen_rtx (UMULT, SImode,
1460: copy_to_mode_reg (SImode, operands[2]),
1461: operands[1]);
1462: else if (GET_CODE (operands[2]) == CONST_INT)
1463: src = gen_rtx (UMULT, SImode,
1464: copy_to_mode_reg (SImode, operands[1]),
1465: operands[2]);
1466: else src = 0;
1467:
1468: if (src)
1469: emit_insn (gen_rtx (SET, VOIDmode, operands[0], src));
1470: else
1471: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
1472: gen_rtx (SET, VOIDmode, operands[0],
1473: gen_rtx (UMULT, SImode, operands[1], operands[2])),
1474: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 8)),
1475: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 9)),
1476: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 12)),
1477: gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 13)))));
1478: DONE;
1479: }")
1480:
1481: (define_insn ""
1482: [(set (match_operand:SI 0 "register_operand" "=r")
1483: (mult:SI (match_operand:SI 1 "register_operand" "r")
1484: (match_operand:SI 2 "immediate_operand" "n")))]
1485: ""
1486: "* return output_mul_by_constant (insn, operands, 0);")
1487:
1488: (define_insn ""
1489: [(set (match_operand:SI 0 "register_operand" "=r")
1490: (umult:SI (match_operand:SI 1 "register_operand" "r")
1491: (match_operand:SI 2 "immediate_operand" "n")))]
1492: ""
1493: "* return output_mul_by_constant (insn, operands, 1);")
1494:
1495: (define_insn ""
1496: [(set (match_operand:SI 0 "register_operand" "=r")
1497: (mult:SI (match_operand:SI 1 "general_operand" "%r")
1498: (match_operand:SI 2 "general_operand" "r")))
1499: (clobber (reg:SI 8))
1500: (clobber (reg:SI 9))
1501: (clobber (reg:SI 12))
1502: (clobber (reg:SI 13))]
1503: ""
1504: "* return output_mul_insn (operands, 0);")
1505:
1506: (define_insn ""
1507: [(set (match_operand:SI 0 "register_operand" "=r")
1508: (umult:SI (match_operand:SI 1 "general_operand" "%r")
1509: (match_operand:SI 2 "general_operand" "r")))
1510: (clobber (reg:SI 8))
1511: (clobber (reg:SI 9))
1512: (clobber (reg:SI 12))
1513: (clobber (reg:SI 13))]
1514: ""
1515: "* return output_mul_insn (operands, 1);")
1516:
1517: ;; this pattern is needed because cse may eliminate the multiplication,
1518: ;; but leave the clobbers behind.
1519:
1520: (define_insn ""
1521: [(set (match_operand:SI 0 "register_operand" "=r")
1522: (match_operand:SI 1 "general_operand" "g"))
1523: (clobber (reg:SI 8))
1524: (clobber (reg:SI 9))
1525: (clobber (reg:SI 12))
1526: (clobber (reg:SI 13))]
1527: ""
1528: "*
1529: {
1530: if (GET_CODE (operands[1]) == CONST_INT)
1531: {
1532: if (SMALL_INT (operands[1]))
1533: return \"mov %1,%0\";
1534: return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
1535: }
1536: if (GET_CODE (operands[1]) == MEM)
1537: return \"ld %1,%0\";
1538: return \"mov %1,%0\";
1539: }")
1540:
1541: ;;- and instructions (with compliment also)
1542: (define_insn "andsi3"
1543: [(set (match_operand:SI 0 "register_operand" "=r")
1544: (and:SI (match_operand:SI 1 "arith32_operand" "%r")
1545: (match_operand:SI 2 "arith32_operand" "rn")))]
1546: ""
1547: "*
1548: {
1549: if (REG_P (operands[2]) || SMALL_INT (operands[2]))
1550: return \"and %1,%2,%0\";
1551: cc_status.flags &= ~CC_KNOW_HI_G1;
1552: return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;and %1,%%g1,%0\";
1553: }")
1554:
1555: (define_insn "andcbsi3"
1556: [(set (match_operand:SI 0 "register_operand" "=r")
1557: (and:SI (match_operand:SI 1 "register_operand" "r")
1558: (not:SI (match_operand:SI 2 "register_operand" "r"))))]
1559: ""
1560: "andn %1,%2,%0")
1561:
1562: (define_insn "iorsi3"
1563: [(set (match_operand:SI 0 "register_operand" "=r")
1564: (ior:SI (match_operand:SI 1 "arith32_operand" "%r")
1565: (match_operand:SI 2 "arith32_operand" "rn")))]
1566: ""
1567: "*
1568: {
1569: if (REG_P (operands[2]) || SMALL_INT (operands[2]))
1570: return \"or %1,%2,%0\";
1571: cc_status.flags &= ~CC_KNOW_HI_G1;
1572: return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;or %1,%%g1,%0\";
1573: }")
1574:
1575: (define_insn "iorcbsi3"
1576: [(set (match_operand:SI 0 "register_operand" "=r")
1577: (ior:SI (match_operand:SI 1 "register_operand" "r")
1578: (not:SI (match_operand:SI 2 "register_operand" "r"))))]
1579: ""
1580: "orn %1,%2,%0")
1581:
1582: (define_insn "xorsi3"
1583: [(set (match_operand:SI 0 "register_operand" "=r")
1584: (xor:SI (match_operand:SI 1 "arith32_operand" "%r")
1585: (match_operand:SI 2 "arith32_operand" "rn")))]
1586: ""
1587: "*
1588: {
1589: if (REG_P (operands[2]) || SMALL_INT (operands[2]))
1590: return \"xor %1,%2,%0\";
1591: cc_status.flags &= ~CC_KNOW_HI_G1;
1592: return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;xor %1,%%g1,%0\";
1593: }")
1594:
1595: (define_insn "xorcbsi3"
1596: [(set (match_operand:SI 0 "register_operand" "=r")
1597: (xor:SI (match_operand:SI 1 "register_operand" "r")
1598: (not:SI (match_operand:SI 2 "register_operand" "r"))))]
1599: ""
1600: "xnor %1,%2,%0")
1601:
1602: ;; We cannot use the "neg" pseudo insn because the Sun assembler
1603: ;; does not know how to make it work for constants.
1604: (define_insn "negsi2"
1605: [(set (match_operand:SI 0 "general_operand" "=r")
1606: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
1607: ""
1608: "sub %%g0,%1,%0")
1609:
1610: ;; We cannot use the "not" pseudo insn because the Sun assembler
1611: ;; does not know how to make it work for constants.
1612: (define_insn "one_cmplsi2"
1613: [(set (match_operand:SI 0 "general_operand" "=r")
1614: (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
1615: ""
1616: "xnor %%g0,%1,%0")
1617:
1618: ;; Floating point arithmetic instructions.
1619:
1620: (define_insn "adddf3"
1621: [(set (match_operand:DF 0 "register_operand" "=f")
1622: (plus:DF (match_operand:DF 1 "register_operand" "f")
1623: (match_operand:DF 2 "register_operand" "f")))]
1624: ""
1625: "faddd %1,%2,%0")
1626:
1627: (define_insn "addsf3"
1628: [(set (match_operand:SF 0 "register_operand" "=f")
1629: (plus:SF (match_operand:SF 1 "register_operand" "f")
1630: (match_operand:SF 2 "register_operand" "f")))]
1631: ""
1632: "fadds %1,%2,%0")
1633:
1634: (define_insn "subdf3"
1635: [(set (match_operand:DF 0 "register_operand" "=f")
1636: (minus:DF (match_operand:DF 1 "register_operand" "f")
1637: (match_operand:DF 2 "register_operand" "f")))]
1638: ""
1639: "fsubd %1,%2,%0")
1640:
1641: (define_insn "subsf3"
1642: [(set (match_operand:SF 0 "register_operand" "=f")
1643: (minus:SF (match_operand:SF 1 "register_operand" "f")
1644: (match_operand:SF 2 "register_operand" "f")))]
1645: ""
1646: "fsubs %1,%2,%0")
1647:
1648: (define_insn "muldf3"
1649: [(set (match_operand:DF 0 "register_operand" "=f")
1650: (mult:DF (match_operand:DF 1 "register_operand" "f")
1651: (match_operand:DF 2 "register_operand" "f")))]
1652: ""
1653: "fmuld %1,%2,%0")
1654:
1655: (define_insn "mulsf3"
1656: [(set (match_operand:SF 0 "register_operand" "=f")
1657: (mult:SF (match_operand:SF 1 "register_operand" "f")
1658: (match_operand:SF 2 "register_operand" "f")))]
1659: ""
1660: "fmuls %1,%2,%0")
1661:
1662: (define_insn "divdf3"
1663: [(set (match_operand:DF 0 "register_operand" "=f")
1664: (div:DF (match_operand:DF 1 "register_operand" "f")
1665: (match_operand:DF 2 "register_operand" "f")))]
1666: ""
1667: "fdivd %1,%2,%0")
1668:
1669: (define_insn "divsf3"
1670: [(set (match_operand:SF 0 "register_operand" "=f")
1671: (div:SF (match_operand:SF 1 "register_operand" "f")
1672: (match_operand:SF 2 "register_operand" "f")))]
1673: ""
1674: "fdivs %1,%2,%0")
1675:
1676: (define_insn "negdf2"
1677: [(set (match_operand:DF 0 "register_operand" "=f")
1678: (neg:DF (match_operand:DF 1 "register_operand" "f")))]
1679: ""
1680: "*
1681: {
1682: output_asm_insn (\"fnegs %1,%0\", operands);
1683: if (REGNO (operands[0]) != REGNO (operands[1]))
1684: {
1685: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
1686: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
1687: output_asm_insn (\"fmovs %1,%0\", operands);
1688: }
1689: return \"\";
1690: }")
1691:
1692: (define_insn "negsf2"
1693: [(set (match_operand:SF 0 "register_operand" "=f")
1694: (neg:SF (match_operand:SF 1 "register_operand" "f")))]
1695: ""
1696: "fnegs %1,%0")
1697:
1698: (define_insn "absdf2"
1699: [(set (match_operand:DF 0 "register_operand" "=f")
1700: (abs:DF (match_operand:DF 1 "register_operand" "f")))]
1701: ""
1702: "*
1703: {
1704: output_asm_insn (\"fabss %1,%0\", operands);
1705: if (REGNO (operands[0]) != REGNO (operands[1]))
1706: {
1707: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
1708: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
1709: output_asm_insn (\"fmovs %1,%0\", operands);
1710: }
1711: return \"\";
1712: }")
1713:
1714: (define_insn "abssf2"
1715: [(set (match_operand:SF 0 "register_operand" "=f")
1716: (abs:SF (match_operand:SF 1 "register_operand" "f")))]
1717: ""
1718: "fabss %1,%0")
1719:
1720: ;; Shift instructions
1721:
1722: ;; Optimized special case of shifting.
1723: ;; Must precede the general case.
1724:
1725: (define_insn ""
1726: [(set (match_operand:SI 0 "register_operand" "=r")
1727: (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
1728: (const_int 24)))]
1729: ""
1730: "*
1731: {
1732: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1733: {
1734: cc_status.flags |= CC_KNOW_HI_G1;
1735: cc_status.mdep = XEXP (operands[1], 0);
1736: return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
1737: }
1738: return \"ldsb %1,%0\";
1739: }")
1740:
1741: (define_insn ""
1742: [(set (match_operand:SI 0 "register_operand" "=r")
1743: (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
1744: (const_int 24)))]
1745: ""
1746: "*
1747: {
1748: if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1749: {
1750: cc_status.flags |= CC_KNOW_HI_G1;
1751: cc_status.mdep = XEXP (operands[1], 0);
1752: return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
1753: }
1754: return \"ldub %1,%0\";
1755: }")
1756:
1757: ;;- arithmetic shift instructions
1758: (define_insn "ashlsi3"
1759: [(set (match_operand:SI 0 "register_operand" "=r")
1760: (ashift:SI (match_operand:SI 1 "register_operand" "r")
1761: (match_operand:SI 2 "arith32_operand" "rn")))]
1762: ""
1763: "*
1764: {
1765: if (GET_CODE (operands[2]) == CONST_INT
1766: && INTVAL (operands[2]) >= 32)
1767: operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
1768: return \"sll %1,%2,%0\";
1769: }")
1770:
1771: (define_insn "ashrsi3"
1772: [(set (match_operand:SI 0 "register_operand" "=r")
1773: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
1774: (match_operand:SI 2 "arith32_operand" "rn")))]
1775: ""
1776: "*
1777: {
1778: if (GET_CODE (operands[2]) == CONST_INT
1779: && INTVAL (operands[2]) >= 32)
1780: operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
1781: return \"sra %1,%2,%0\";
1782: }")
1783:
1784: (define_insn "lshrsi3"
1785: [(set (match_operand:SI 0 "register_operand" "=r")
1786: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
1787: (match_operand:SI 2 "arith32_operand" "rn")))]
1788: ""
1789: "*
1790: {
1791: if (GET_CODE (operands[2]) == CONST_INT
1792: && INTVAL (operands[2]) >= 32)
1793: operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
1794: return \"srl %1,%2,%0\";
1795: }")
1796:
1797: ;; Unconditional and other jump instructions
1798: ;; Note that for the Sparc, by setting the annul bit on an unconditional
1799: ;; branch, the following insn is never executed. This saves us a nop,
1800: ;; but requires a debugger which can handle annuled branches.
1801: (define_insn "jump"
1802: [(set (pc) (label_ref (match_operand 0 "" "")))]
1803: ""
1804: "*
1805: {
1806: extern int optimize;
1807: extern int flag_no_peephole;
1808:
1809: if (optimize && !flag_no_peephole)
1810: return \"b,a %l0\";
1811: return \"b %l0\;nop\";
1812: }")
1813:
1814: ;; Peephole optimizers recognize a few simple cases when delay insns are safe.
1815: ;; Complex ones are up front. Simple ones after.
1816:
1817: ;; This pattern is just like the following one, but matches when there
1818: ;; is a jump insn after the "delay" insn. Without this pattern, we
1819: ;; de-optimize that case.
1820:
1821: (define_peephole
1822: [(set (pc) (match_operand 0 "" ""))
1823: (set (match_operand:SI 1 "" "")
1824: (match_operand:SI 2 "" ""))
1825: (set (pc) (label_ref (match_operand 3 "" "")))]
1826: "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 2)"
1827: "*
1828: {
1829: rtx xoperands[2];
1830: rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]);
1831: rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
1832: rtx label, head;
1833: int parity;
1834:
1835: if (GET_CODE (XEXP (operands[0], 1)) == PC)
1836: {
1837: parity = 1;
1838: label = XEXP (XEXP (operands[0], 2), 0);
1839: }
1840: else
1841: {
1842: parity = 0;
1843: label = XEXP (XEXP (operands[0], 1), 0);
1844: }
1845: xoperands[0] = XEXP (operands[0], 0);
1846: xoperands[1] = label;
1847:
1848: head = next_real_insn_no_labels (label);
1849:
1850: /* If at the target of this label we set the condition codes,
1851: and the condition codes are already set for that value,
1852: advance, if we can, to the following insn. */
1853: if (GET_CODE (PATTERN (head)) == SET
1854: && GET_CODE (SET_DEST (PATTERN (head))) == CC0
1855: && cc_status.value2 == SET_SRC (PATTERN (head)))
1856: {
1857: rtx nhead = next_real_insn_no_labels (head);
1858: if (nhead
1859: && GET_CODE (nhead) == INSN
1860: && GET_CODE (PATTERN (nhead)) == SET
1861: && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)),
1862: GET_MODE (SET_DEST (PATTERN (nhead))))
1863: && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode))
1864: {
1865: head = nhead;
1866: }
1867: }
1868:
1869: /* Output the branch instruction first. */
1870: if (cc_prev_status.flags & CC_IN_FCCR)
1871: {
1872: if (parity)
1873: output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands);
1874: else
1875: output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands);
1876: }
1877: else
1878: {
1879: if (parity)
1880: output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands);
1881: else
1882: output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands);
1883: }
1884:
1885: /* Now steal the first insn of the target. */
1886: output_eager_then_insn (head, operands);
1887:
1888: XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 1);
1889: XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 2);
1890:
1891: return output_delayed_branch (\"b %l3 ! eager2\", operands, insn);
1892: }")
1893:
1894: ;; Here is a peephole which recognizes where delay insns can be made safe:
1895: ;; (1) following a conditional branch, if the target of the conditional branch
1896: ;; has only one user (this insn), move the first insn into our delay slot
1897: ;; and emit an annulled branch.
1898: ;; (2) following a conditional branch, if we can execute the fall-through
1899: ;; insn without risking any evil effects, then do that instead of a nop.
1900:
1901: (define_peephole
1902: [(set (pc) (match_operand 0 "" ""))
1903: (set (match_operand:SI 1 "" "")
1904: (match_operand:SI 2 "" ""))]
1905: "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 1)"
1906: "*
1907: {
1908: rtx xoperands[2];
1909: rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]);
1910: rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
1911: rtx label, head, prev = (rtx)1;
1912: int parity;
1913:
1914: if (GET_CODE (XEXP (operands[0], 1)) == PC)
1915: {
1916: parity = 1;
1917: label = XEXP (XEXP (operands[0], 2), 0);
1918: }
1919: else
1920: {
1921: parity = 0;
1922: label = XEXP (XEXP (operands[0], 1), 0);
1923: }
1924: xoperands[0] = XEXP (operands[0], 0);
1925: xoperands[1] = label;
1926:
1927: if (LABEL_NUSES (label) == 1)
1928: {
1929: prev = PREV_INSN (label);
1930: while (prev
1931: && (GET_CODE (prev) == NOTE
1932: || (GET_CODE (prev) == INSN
1933: && (GET_CODE (PATTERN (prev)) == CLOBBER
1934: || GET_CODE (PATTERN (prev)) == USE))))
1935: prev = PREV_INSN (prev);
1936: if (prev == 0
1937: || GET_CODE (prev) == BARRIER)
1938: {
1939: prev = 0;
1940: head = next_real_insn_no_labels (label);
1941: }
1942: }
1943: if (prev == 0
1944: && head != 0
1945: && ! INSN_DELETED_P (head)
1946: && GET_CODE (head) == INSN
1947: && GET_CODE (PATTERN (head)) == SET
1948: && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
1949: GET_MODE (SET_DEST (PATTERN (head))))
1950: && strict_single_insn_op_p (SET_DEST (PATTERN (head)), VOIDmode))
1951: {
1952: /* If at the target of this label we set the condition codes,
1953: and the condition codes are already set for that value,
1954: advance, if we can, to the following insn. */
1955: if (GET_CODE (PATTERN (head)) == SET
1956: && GET_CODE (SET_DEST (PATTERN (head))) == CC0
1957: && cc_status.value2 == SET_SRC (PATTERN (head)))
1958: {
1959: rtx nhead = next_real_insn_no_labels (head);
1960: if (nhead
1961: && GET_CODE (nhead) == INSN
1962: && GET_CODE (PATTERN (nhead)) == SET
1963: && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)),
1964: GET_MODE (SET_DEST (nhead)))
1965: && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode))
1966: head = nhead;
1967: }
1968:
1969: /* Output the branch instruction first. */
1970: if (cc_prev_status.flags & CC_IN_FCCR)
1971: {
1972: if (parity)
1973: output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands);
1974: else
1975: output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands);
1976: }
1977: else
1978: {
1979: if (parity)
1980: output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands);
1981: else
1982: output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands);
1983: }
1984:
1985: /* Now steal the first insn of the target. */
1986: output_eager_then_insn (head, operands);
1987: }
1988: else
1989: {
1990: /* Output the branch instruction first. */
1991: if (cc_prev_status.flags & CC_IN_FCCR)
1992: {
1993: if (parity)
1994: output_asm_insn (\"fb%F0 %l1 ! eager\", xoperands);
1995: else
1996: output_asm_insn (\"fb%C0 %l1 ! eager\", xoperands);
1997: }
1998: else
1999: {
2000: if (parity)
2001: output_asm_insn (\"b%N0 %l1 ! eager\", xoperands);
2002: else
2003: output_asm_insn (\"b%C0 %l1 ! eager\", xoperands);
2004: }
2005: }
2006: return output_delay_insn (delay_insn);
2007: }")
2008:
2009: ;; Here are two simple peepholes which fill the delay slot of
2010: ;; an unconditional branch.
2011:
2012: (define_peephole
2013: [(set (match_operand:SI 0 "register_operand" "=r")
2014: (match_operand:SI 1 "single_insn_src_p" "p"))
2015: (set (pc) (label_ref (match_operand 2 "" "")))]
2016: ""
2017: "* return output_delayed_branch (\"b %l2\", operands, insn);")
2018:
2019: (define_peephole
2020: [(set (match_operand:SI 0 "memory_operand" "=m")
2021: (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2022: (set (pc) (label_ref (match_operand 2 "" "")))]
2023: ""
2024: "* return output_delayed_branch (\"b %l2\", operands, insn);")
2025:
2026: (define_insn "tablejump"
2027: [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2028: (use (label_ref (match_operand 1 "" "")))]
2029: ""
2030: "jmp %0\;nop")
2031:
2032: (define_peephole
2033: [(set (match_operand:SI 0 "register_operand" "=r")
2034: (match_operand:SI 1 "single_insn_src_p" "p"))
2035: (set (pc) (match_operand:SI 2 "register_operand" "r"))
2036: (use (label_ref (match_operand 3 "" "")))]
2037: "REGNO (operands[0]) != REGNO (operands[2])"
2038: "* return output_delayed_branch (\"jmp %2\", operands, insn);")
2039:
2040: (define_peephole
2041: [(set (match_operand:SI 0 "memory_operand" "=m")
2042: (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2043: (set (pc) (match_operand:SI 2 "register_operand" "r"))
2044: (use (label_ref (match_operand 3 "" "")))]
2045: ""
2046: "* return output_delayed_branch (\"jmp %2\", operands, insn);")
2047:
2048: ;;- jump to subroutine
2049: (define_expand "call"
2050: [(call (match_operand:SI 0 "memory_operand" "m")
2051: (match_operand 1 "" "i"))]
2052: ;; operand[2] is next_arg_register
2053: ""
2054: "
2055: {
2056: rtx fn_rtx, nregs_rtx;
2057:
2058: if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[0], 0)) == REG)
2059: {
2060: rtx g1_rtx = gen_rtx (REG, SImode, 1);
2061: emit_move_insn (g1_rtx, XEXP (operands[0], 0));
2062: fn_rtx = gen_rtx (MEM, SImode, g1_rtx);
2063: }
2064: else
2065: fn_rtx = operands[0];
2066:
2067: /* Count the number of parameter registers being used by this call.
2068: if that argument is NULL, it means we are using them all, which
2069: means 6 on the sparc. */
2070: #if 0
2071: if (operands[2])
2072: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
2073: else
2074: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2075: #else
2076: nregs_rtx = const0_rtx;
2077: #endif
2078:
2079: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2080: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
2081: gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)))));
2082: DONE;
2083: }")
2084:
2085: (define_insn ""
2086: [(call (match_operand:SI 0 "memory_operand" "m")
2087: (match_operand 1 "" "i"))
2088: (use (reg:SI 31))]
2089: ;;- Don't use operand 1 for most machines.
2090: ""
2091: "*
2092: {
2093: /* strip the MEM. */
2094: operands[0] = XEXP (operands[0], 0);
2095: CC_STATUS_INIT;
2096: if (TARGET_SUN_ASM && GET_CODE (operands[0]) == REG)
2097: return \"jmpl %a0,%%o7\;nop\";
2098: return \"call %a0,%1\;nop\";
2099: }")
2100:
2101: (define_peephole
2102: [(set (match_operand:SI 0 "register_operand" "=r")
2103: (match_operand:SI 1 "single_insn_src_p" "p"))
2104: (parallel [(call (match_operand:SI 2 "memory_operand" "m")
2105: (match_operand 3 "" "i"))
2106: (use (reg:SI 31))])]
2107: ;;- Don't use operand 1 for most machines.
2108: "! reg_mentioned_p (operands[0], operands[2])"
2109: "*
2110: {
2111: /* strip the MEM. */
2112: operands[2] = XEXP (operands[2], 0);
2113: if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG)
2114: return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn);
2115: return output_delayed_branch (\"call %a2,%3\", operands, insn);
2116: }")
2117:
2118: (define_peephole
2119: [(set (match_operand:SI 0 "memory_operand" "=m")
2120: (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2121: (parallel [(call (match_operand:SI 2 "memory_operand" "m")
2122: (match_operand 3 "" "i"))
2123: (use (reg:SI 31))])]
2124: ;;- Don't use operand 1 for most machines.
2125: ""
2126: "*
2127: {
2128: /* strip the MEM. */
2129: operands[2] = XEXP (operands[2], 0);
2130: if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG)
2131: return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn);
2132: return output_delayed_branch (\"call %a2,%3\", operands, insn);
2133: }")
2134:
2135: (define_expand "call_value"
2136: [(set (match_operand 0 "register_operand" "=rf")
2137: (call (match_operand:SI 1 "memory_operand" "m")
2138: (match_operand 2 "" "i")))]
2139: ;; operand 3 is next_arg_register
2140: ""
2141: "
2142: {
2143: rtx fn_rtx, nregs_rtx;
2144: rtvec vec;
2145:
2146: if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[1], 0)) == REG)
2147: {
2148: rtx g1_rtx = gen_rtx (REG, SImode, 1);
2149: emit_move_insn (g1_rtx, XEXP (operands[1], 0));
2150: fn_rtx = gen_rtx (MEM, SImode, g1_rtx);
2151: }
2152: else
2153: fn_rtx = operands[1];
2154:
2155: #if 0
2156: if (operands[3])
2157: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
2158: else
2159: nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
2160: #else
2161: nregs_rtx = const0_rtx;
2162: #endif
2163:
2164: vec = gen_rtvec (2,
2165: gen_rtx (SET, VOIDmode, operands[0],
2166: gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
2167: gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
2168:
2169: emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
2170: DONE;
2171: }")
2172:
2173: (define_insn ""
2174: [(set (match_operand 0 "" "=rf")
2175: (call (match_operand:SI 1 "memory_operand" "m")
2176: (match_operand 2 "" "i")))
2177: (use (reg:SI 31))]
2178: ;;- Don't use operand 2 for most machines.
2179: ""
2180: "*
2181: {
2182: /* strip the MEM. */
2183: operands[1] = XEXP (operands[1], 0);
2184: CC_STATUS_INIT;
2185: if (TARGET_SUN_ASM && GET_CODE (operands[1]) == REG)
2186: return \"jmpl %a1,%%o7\;nop\";
2187: return \"call %a1,%2\;nop\";
2188: }")
2189:
2190: (define_peephole
2191: [(set (match_operand:SI 0 "register_operand" "=r")
2192: (match_operand:SI 1 "single_insn_src_p" "p"))
2193: (parallel [(set (match_operand 2 "" "=rf")
2194: (call (match_operand:SI 3 "memory_operand" "m")
2195: (match_operand 4 "" "i")))
2196: (use (reg:SI 31))])]
2197: ;;- Don't use operand 4 for most machines.
2198: "! reg_mentioned_p (operands[0], operands[3])"
2199: "*
2200: {
2201: /* strip the MEM. */
2202: operands[3] = XEXP (operands[3], 0);
2203: if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG)
2204: return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn);
2205: return output_delayed_branch (\"call %a3,%4\", operands, insn);
2206: }")
2207:
2208: (define_peephole
2209: [(set (match_operand:SI 0 "memory_operand" "=m")
2210: (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2211: (parallel [(set (match_operand 2 "" "=rf")
2212: (call (match_operand:SI 3 "memory_operand" "m")
2213: (match_operand 4 "" "i")))
2214: (use (reg:SI 31))])]
2215: ;;- Don't use operand 4 for most machines.
2216: ""
2217: "*
2218: {
2219: /* strip the MEM. */
2220: operands[3] = XEXP (operands[3], 0);
2221: if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG)
2222: return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn);
2223: return output_delayed_branch (\"call %a3,%4\", operands, insn);
2224: }")
2225:
2226: (define_insn "return"
2227: [(return)]
2228: "! TARGET_EPILOGUE"
2229: "ret\;restore")
2230:
2231: (define_peephole
2232: [(set (reg:SI 24)
2233: (match_operand:SI 0 "reg_or_0_operand" "rJ"))
2234: (return)]
2235: "! TARGET_EPILOGUE"
2236: "ret\;restore %r0,0x0,%%o0")
2237:
2238: (define_peephole
2239: [(set (reg:SI 24)
2240: (plus:SI (match_operand:SI 0 "register_operand" "r%")
2241: (match_operand:SI 1 "arith_operand" "rI")))
2242: (return)]
2243: "! TARGET_EPILOGUE"
2244: "ret\;restore %r0,%1,%%o0")
2245:
2246: (define_peephole
2247: [(set (reg:SI 24)
2248: (minus:SI (match_operand:SI 0 "register_operand" "r")
2249: (match_operand:SI 1 "small_int" "I")))
2250: (return)]
2251: "! TARGET_EPILOGUE"
2252: "ret\;restore %0,-(%1),%%o0")
2253:
2254: (define_insn "nop"
2255: [(const_int 0)]
2256: ""
2257: "nop")
2258:
2259: ;;- Local variables:
2260: ;;- mode:emacs-lisp
2261: ;;- comment-start: ";;- "
2262: ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
2263: ;;- eval: (modify-syntax-entry ?[ "(]")
2264: ;;- eval: (modify-syntax-entry ?] ")[")
2265: ;;- eval: (modify-syntax-entry ?{ "(}")
2266: ;;- eval: (modify-syntax-entry ?} "){")
2267: ;;- End:
2268:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.