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