Oh GACK! src-clean doesn't quite work that easily since cleandist rebuilds the
[unix-history] / gnu / usr.bin / gcc1 / cc1 / config / i386.md
CommitLineData
15637ed4
RG
1;;
2;; This code is derived from software copyrighted by the Free Software
3;; Foundation.
4;;
5;; Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6;;
7;; @(#)i386.md 6.2 (Berkeley) 5/8/91
8;;
9
10;; GCC machine description for Intel 80386.
11;; Copyright (C) 1988 Free Software Foundation, Inc.
12;; Mostly by William Schelter.
13
14;; This file is part of GNU CC.
15
16;; GNU CC is free software; you can redistribute it and/or modify
17;; it under the terms of the GNU General Public License as published by
18;; the Free Software Foundation; either version 1, or (at your option)
19;; any later version.
20
21;; GNU CC is distributed in the hope that it will be useful,
22;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24;; GNU General Public License for more details.
25
26;; You should have received a copy of the GNU General Public License
27;; along with GNU CC; see the file COPYING. If not, write to
28;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29
30
31;;- instruction definitions
32
33;;- @@The original PO technology requires these to be ordered by speed,
34;;- @@ so that assigner will pick the fastest.
35
36;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
37
38;;- When naming insn's (operand 0 of define_insn) be careful about using
39;;- names from other targets machine descriptions.
40
41;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
42;;- updates for most instructions.
43
44;;- Operand classes for the register allocator:
45;;- 'a' for eax
46;;- 'd' for edx
47;;- 'c' for ecx
48;;- 'b' for ebx
49;;- 'f' for anything in FLOAT_REGS
50;;- 'r' any (non-floating-point) register
51;;- 'q' regs that allow byte operations (A, B, C and D)
52;;- 'A' A and D registers
53
54;; the special asm out single letter directives following a '%' are:
55;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of operands[1]
56;; 's' output a '*'
57;; 'w' If the operand is a REG, it uses the mode size to determine the
58;; printing of the reg
59
60\f
61;; Put tstsi first among test insns so it matches a CONST_INT operand.
62
63(define_insn "tstsi"
64 [(set (cc0)
65 (match_operand:SI 0 "general_operand" "rm"))]
66 ""
67 "*
68{
69 operands[1] = const0_rtx;
70 if (REG_P (operands[0]))
71 return AS2 (test%L0,%0,%0);
72 return AS2 (cmp%L0,%1,%0);
73}")
74
75(define_insn "tsthi"
76 [(set (cc0)
77 (match_operand:HI 0 "general_operand" "rm"))]
78 ""
79 "*
80{
81 operands[1] = const0_rtx;
82 if (REG_P (operands[0]))
83 return AS2 (test%W0,%0,%0);
84 return AS2 (cmp%W0,%1,%0);
85}")
86
87(define_insn "tstqi"
88 [(set (cc0)
89 (match_operand:QI 0 "general_operand" "qm"))]
90 ""
91 "*
92{
93 operands[1] = const0_rtx;
94 if (REG_P (operands[0]))
95 return AS2 (test%B0,%0,%0);
96 return AS2 (cmp%B0,%1,%0);
97}")
98
99(define_insn "tstsf"
100 [(set (cc0)
101 (match_operand:SF 0 "general_operand" "rm,f"))
102 (clobber (reg:SI 0))]
103 "TARGET_80387"
104 "*
105{
106 rtx xops[1];
107 if (!FP_REG_P (operands[0]))
108 fp_push_sf (operands[0]);
109/* fp_pop_level--; */
110 xops[0] = FP_TOP;
111 cc_status.flags |= CC_IN_80387;
112 if (FP_REG_P (operands[0]) && ! top_dead_p (insn))
113 output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops);
114 else
115 output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops);
116 RETCOM (testsf);
117}")
118
119(define_insn "tstdf"
120 [(set (cc0)
121 (match_operand:DF 0 "general_operand" "rm,f"))
122 (clobber (reg:SI 0))
123 ]
124 "TARGET_80387"
125 "*
126{
127 rtx xops[1];
128 if (!FP_REG_P (operands[0]))
129 fp_push_df (operands[0]);
130/* fp_pop_level--; */
131 xops[0] = FP_TOP;
132 cc_status.flags |= CC_IN_80387;
133 if (FP_REG_P (operands[0]) && ! top_dead_p (insn))
134 output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops);
135 else
136 output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops);
137 RETCOM (testdf);
138}")
139\f
140;;- compare instructions
141
142;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
143
144(define_insn "cmpsi"
145 [(set (cc0)
146 (compare (match_operand:SI 0 "general_operand" "mr,ri")
147 (match_operand:SI 1 "general_operand" "ri,mr")))]
148 ""
149 "*
150{
151 if (REG_P (operands[1])
152 || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
153 {
154 cc_status.flags |= CC_REVERSED;
155 return AS2 (cmp%L0,%0,%1);
156 }
157 return AS2 (cmp%L0,%1,%0);
158}")
159
160(define_insn "cmphi"
161 [(set (cc0)
162 (compare (match_operand:HI 0 "general_operand" "mr,ri")
163 (match_operand:HI 1 "general_operand" "ri,mr")))]
164 ""
165 "*
166{
167 if (REG_P (operands[1])
168 || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
169 {
170 cc_status.flags |= CC_REVERSED;
171 return AS2 (cmp%W0,%0,%1);
172 }
173 return AS2 (cmp%W0,%1,%0);
174}")
175
176(define_insn "cmpqi"
177 [(set (cc0)
178 (compare (match_operand:QI 0 "general_operand" "qn,mq")
179 (match_operand:QI 1 "general_operand" "qm,nq")))]
180 ""
181 "*
182{
183 if (REG_P (operands[1])
184 || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
185 {
186 cc_status.flags |= CC_REVERSED;
187 return AS2 (cmp%B0,%0,%1);
188 }
189 return AS2 (cmp%B0,%1,%0);
190}")
191
192(define_insn "cmpdf"
193 [(set (cc0)
194 (compare (match_operand:DF 0 "general_operand" "m,f*r,m,f,r,!*r")
195 (match_operand:DF 1 "general_operand" "m,m,f*r,r,f,*r")))
196 (clobber (reg:SI 0))]
197 "TARGET_80387"
198 "*
199{
200 if (FP_REG_P (operands[0]))
201 {
202 rtx tem = operands[1];
203 operands[1] = operands[0];
204 operands[0] = tem;
205 cc_status.flags |= CC_REVERSED;
206 }
207 if (! FP_REG_P (operands[1]))
208 output_movdf (FP_TOP, operands[1]);
209 output_movdf (FP_TOP, operands[0]);
210/* fp_pop_level--;
211 fp_pop_level--; */
212 cc_status.flags |= CC_IN_80387;
213 return \"fcompp\;fnstsw %R0ax\;sahf\";
214}")
215
216(define_insn "cmpsf"
217 [(set (cc0)
218 (compare (match_operand:SF 0 "general_operand" "m,f*r,m,f,r,!*r")
219 (match_operand:SF 1 "general_operand" "m,m,f*r,r,f,*r")))
220 (clobber (reg:SI 0))]
221 "TARGET_80387"
222 "*
223{
224 if (FP_REG_P (operands[0]))
225 {
226 rtx tem = operands[1];
227 operands[1] = operands[0];
228 operands[0] = tem;
229 cc_status.flags |= CC_REVERSED;
230 }
231 if (! FP_REG_P (operands[1]))
232 output_movsf (FP_TOP, operands[1]);
233 output_movsf (FP_TOP, operands[0]);
234/* fp_pop_level--;
235 fp_pop_level--; */
236 cc_status.flags |= CC_IN_80387;
237 return \"fcompp\;fnstsw %R0ax\;sahf\";
238}")
239
240;; logical compare
241(define_insn ""
242 [(set (cc0)
243 (and:SI (match_operand:SI 0 "general_operand" "rm,ri")
244 (match_operand:SI 1 "general_operand" "ri,rm")))]
245 ""
246 "*
247{
248 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
249 return AS2 (test%L0,%1,%0);
250 return AS2 (test%L0,%0,%1);
251}")
252
253(define_insn ""
254 [(set (cc0)
255 (and:HI (match_operand:HI 0 "general_operand" "rm,ri")
256 (match_operand:HI 1 "general_operand" "ri,rm")))]
257 ""
258 "*
259{
260 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
261 return AS2 (test%W0,%1,%0);
262 return AS2 (test%W0,%0,%1);
263}")
264
265(define_insn ""
266 [(set (cc0)
267 (and:QI (match_operand:QI 0 "general_operand" "qm,qi")
268 (match_operand:QI 1 "general_operand" "qi,qm")))]
269 ""
270 "*
271{
272 if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
273 return AS2 (test%B0,%1,%0);
274 return AS2 (test%B0,%0,%1);
275}")
276\f
277;; move instructions.
278;; There is one for each machine mode,
279;; and each is preceded by a corresponding push-insn pattern
280;; (since pushes are not general_operands on the 386).
281
282(define_insn ""
283 [(set (match_operand:SI 0 "push_operand" "=<")
284 (match_operand:SI 1 "general_operand" "g"))]
285 ""
286 "push%L0 %1")
287
288;; General case of fullword move.
289(define_insn "movsi"
290 [(set (match_operand:SI 0 "general_operand" "=g,r")
291 (match_operand:SI 1 "general_operand" "ri,m"))]
292 ""
293 "*
294{
295 rtx link;
296 if (operands[1] == const0_rtx && REG_P (operands[0]))
297 return \"xor%L0 %0,%0\";
298 if (operands[1] == const1_rtx
299 && (link = find_reg_note (insn, REG_WAS_0, 0))
300 /* Make sure the insn that stored the 0 is still present. */
301 && ! XEXP (link, 0)->volatil
302 && GET_CODE (XEXP (link, 0)) != NOTE
303 /* Make sure cross jumping didn't happen here. */
304 && no_labels_between_p (XEXP (link, 0), insn))
305 /* Fastest way to change a 0 to a 1. */
306 return \"inc%L0 %0\";
307 return \"mov%L0 %1,%0\";
308}")
309
310(define_insn ""
311 [(set (match_operand:HI 0 "push_operand" "=<")
312 (match_operand:HI 1 "general_operand" "g"))]
313 ""
314 "push%W0 %1")
315
316(define_insn "movhi"
317 [(set (match_operand:HI 0 "general_operand" "=g,r")
318 (match_operand:HI 1 "general_operand" "ri,m"))]
319 ""
320 "*
321{
322 rtx link;
323 if (operands[1] == const0_rtx && REG_P (operands[0]))
324 return \"xor%W0 %0,%0\";
325 if (operands[1] == const1_rtx
326 && (link = find_reg_note (insn, REG_WAS_0, 0))
327 /* Make sure the insn that stored the 0 is still present. */
328 && ! XEXP (link, 0)->volatil
329 && GET_CODE (XEXP (link, 0)) != NOTE
330 /* Make sure cross jumping didn't happen here. */
331 && no_labels_between_p (XEXP (link, 0), insn))
332 /* Fastest way to change a 0 to a 1. */
333 return \"inc%W0 %0\";
334 return \"mov%W0 %1,%0\";
335}")
336
337;; emit_push_insn when it calls move_by_pieces
338;; requires an insn to "push a byte".
339;; But actually we use pushw, which has the effect of rounding
340;; the amount pushed up to a halfword.
341(define_insn ""
342 [(set (match_operand:QI 0 "push_operand" "=<")
343 (match_operand:QI 1 "general_operand" "q"))]
344 ""
345 "*
346{
347 operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
348 return \"push%W0 %1\";
349}")
350
351(define_insn "movqi"
352 [(set (match_operand:QI 0 "general_operand" "=q,*r,m")
353 (match_operand:QI 1 "general_operand" "*g,q,qi"))]
354 ""
355 "*
356{
357 rtx link;
358 if (operands[1] == const0_rtx && REG_P (operands[0]))
359 return \"xor%B0 %0,%0\";
360 if (operands[1] == const1_rtx
361 && (link = find_reg_note (insn, REG_WAS_0, 0))
362 /* Make sure the insn that stored the 0 is still present. */
363 && ! XEXP (link, 0)->volatil
364 && GET_CODE (XEXP (link, 0)) != NOTE
365 /* Make sure cross jumping didn't happen here. */
366 && no_labels_between_p (XEXP (link, 0), insn))
367 /* Fastest way to change a 0 to a 1. */
368 return \"inc%B0 %0\";
369 /* If mov%B0 isn't allowed for one of these regs, use mov%W0. */
370 if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
371 return (AS2 (mov%W0,%w1,%w0));
372 return (AS2 (mov%B0,%1,%0));
373}")
374
375; I suspect nothing can ever match this ???
376;(define_insn ""
377; [(set (match_operand:SF 0 "general_operand" "rm")
378; (match_operand:SF 1 "general_operand" "f"))
379; (clobber (reg:SF 8))]
380; ""
381; "*
382;{
383; output_asm_insn ("???", operands);
384; fpop_sf (operands[0]);
385; RETCOM (movsf_clobber);
386;}")
387
388(define_insn ""
389 [(set (match_operand:SF 0 "push_operand" "=<,<")
390 (match_operand:SF 1 "general_operand" "gF,f"))]
391 ""
392 "*
393{
394 if (FP_REG_P (operands[1]))
395 {
396 rtx xops[3];
397 xops[0] = AT_SP (SFmode);
398 xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
399 xops[2] = stack_pointer_rtx;
400/* fp_pop_level--; */
401 output_asm_insn (AS2 (sub%L0,%1,%2), xops);
402 if (top_dead_p (insn))
403 output_asm_insn (\"fstp%S0 %0\", xops);
404 else
405 output_asm_insn (\"fst%S0 %0\", xops);
406 RET;
407 }
408 return \"push%L0 %1\";
409}")
410
411(define_insn "movsf"
412 ;; `rf' is duplicated in the second alternative
413 ;; to make sure an optional reload is generated
414 ;; for the memref in operand 0. Otherwise
415 ;; we could use too many hard regs.
416 [(set (match_operand:SF 0 "general_operand" "=rf,mrf,!rm")
417 (match_operand:SF 1 "general_operand" "mrf,rf,F"))]
418 ""
419 "*
420{
421 if (FP_REG_P (operands[1])
422 && !FP_REG_P (operands[0])
423 && !top_dead_p (insn))
424 fp_store_sf (operands[0]);
425 else
426 output_movsf (operands[0], operands[1]);
427 RETCOM (movsf);
428}")
429
430;;should change to handle the memory operands[1] without doing df push..
431(define_insn ""
432 [(set (match_operand:DF 0 "push_operand" "=<,<")
433 (match_operand:DF 1 "general_operand" "gF,f"))]
434 ""
435 "*
436{
437 if (FP_REG_P (operands[1]))
438 {
439 rtx xops[3];
440 xops[0] = AT_SP (DFmode);
441 xops[1] = gen_rtx (CONST_INT, VOIDmode, 8);
442 xops[2] = stack_pointer_rtx;
443/* fp_pop_level--; */
444 output_asm_insn (AS2 (sub%L0,%1,%2), xops);
445 if (top_dead_p(insn))
446 output_asm_insn (\"fstp%Q0 %0\", xops);
447 else
448 output_asm_insn (\"fst%Q0 %0\", xops);
449 RETCOM (pushdf);
450 }
451 else
452 return output_move_double (operands);
453}")
454
455(define_insn "movdf"
456 [(set (match_operand:DF 0 "general_operand" "=rmf,&fr,!rm")
457 ;; `rf' is duplicated in the second alternative
458 ;; to make sure that optional reloads are generated
459 ;; for the memory reference in operand 1.
460 (match_operand:DF 1 "general_operand" "fr,mrf,F"))]
461 ""
462 "*
463{
464 if (FP_REG_P (operands[1])
465 && ! FP_REG_P (operands[0])
466 && ! top_dead_p (insn))
467 fp_store_df (operands[0]);
468 else
469 output_movdf (operands[0], operands[1]);
470 RETCOM (movdf);
471}")
472
473(define_insn ""
474 [(set (match_operand:DI 0 "push_operand" "=<")
475 (match_operand:DI 1 "general_operand" "roiF"))]
476 ""
477 "*
478{
479 return output_move_double (operands);
480}")
481
482(define_insn "movdi"
483 [(set (match_operand:DI 0 "general_operand" "=&r,rm")
484 (match_operand:DI 1 "general_operand" "m,riF"))]
485 ""
486 "*
487{
488 return output_move_double (operands);
489}")
490\f
491;; These go after the move instructions
492;; because the move instructions are better (require no spilling)
493;; when they can apply. But these go before the add and subtract insns
494;; because it is often shorter to use these when both apply.
495
496;Lennart Augustsson <augustss@cs.chalmers.se>
497;says this pattern just makes slower code:
498; pushl %ebp
499; addl $-80,(%esp)
500;instead of
501; leal -80(%ebp),%eax
502; pushl %eax
503;
504;(define_insn ""
505; [(set (match_operand:SI 0 "push_operand" "=<")
506; (plus:SI (match_operand:SI 1 "general_operand" "%r")
507; (match_operand:SI 2 "general_operand" "ri")))]
508; ""
509; "*
510;{
511; rtx xops[4];
512; xops[0] = operands[0];
513; xops[1] = operands[1];
514; xops[2] = operands[2];
515; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
516; output_asm_insn (\"push%z1 %1\", xops);
517; output_asm_insn (AS2 (add%z3,%2,%3), xops);
518; RET;
519;}")
520
521(define_insn ""
522 [(set (match_operand:SI 0 "general_operand" "=g")
523 (plus:SI (match_operand:SI 1 "general_operand" "0")
524 (const_int 1)))]
525 ""
526 "inc%L0 %0")
527
528(define_insn ""
529 [(set (match_operand:SI 0 "general_operand" "=g")
530 (plus:SI (match_operand:SI 1 "general_operand" "0")
531 (const_int -1)))]
532 ""
533 "dec%L0 %0")
534
535(define_insn ""
536 [(set (match_operand:SI 0 "general_operand" "=g")
537 (minus:SI (match_operand:SI 1 "general_operand" "0")
538 (const_int 1)))]
539 ""
540 "dec%L0 %0")
541
542(define_insn ""
543 [(set (match_operand:SI 0 "register_operand" "=r")
544 (match_operand:QI 1 "address_operand" "p"))]
545 ""
546 "*
547{
548 CC_STATUS_INIT;
549 /* Adding a constant to a register is faster with an add. */
550 if (GET_CODE (operands[1]) == PLUS
551 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
552 && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
553 {
554 operands[1] = XEXP (operands[1], 1);
555 return AS2 (add%L0,%1,%0);
556 }
557 return \"lea%L0 %a1,%0\";
558}")
559\f
560;;- conversion instructions
561;;- NONE
562
563;;- truncation instructions
564(define_insn "truncsiqi2"
565 [(set (match_operand:QI 0 "general_operand" "=q,m")
566 (truncate:QI
567 (match_operand:SI 1 "general_operand" "qim,qn")))]
568 ""
569 "*
570{
571 if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
572 return \"mov%L0 %1,%k0\";
573 return \"mov%B0 %b1,%0\";
574}")
575
576(define_insn "trunchiqi2"
577 [(set (match_operand:QI 0 "general_operand" "=q,m")
578 (truncate:QI
579 (match_operand:HI 1 "general_operand" "qim,qn")))]
580 ""
581 "*
582{
583 if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
584 return \"mov%W0 %1,%w0\";
585 return \"mov%B0 %b1,%0\";
586}")
587
588(define_insn "truncsihi2"
589 [(set (match_operand:HI 0 "general_operand" "=r,m")
590 (truncate:HI
591 (match_operand:SI 1 "general_operand" "rim,rn")))]
592 ""
593 "*
594{
595 if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
596 return \"mov%L0 %1,%k0\";
597 return \"mov%W0 %w1,%0\";
598}")
599\f
600;;- zero extension instructions
601;; Note that the one starting from HImode comes before those for QImode
602;; so that a constant operand will match HImode, not QImode.
603
604(define_insn "zero_extendhisi2"
605 [(set (match_operand:SI 0 "general_operand" "=r")
606 (zero_extend:SI
607 (match_operand:HI 1 "general_operand" "rm")))]
608 ""
609 "movz%W0%L0 %1,%0")
610
611(define_insn "zero_extendqihi2"
612 [(set (match_operand:HI 0 "general_operand" "=r")
613 (zero_extend:HI
614 (match_operand:QI 1 "general_operand" "qm")))]
615 ""
616 "movz%B0%W0 %1,%0")
617
618(define_insn "zero_extendqisi2"
619 [(set (match_operand:SI 0 "general_operand" "=r")
620 (zero_extend:SI
621 (match_operand:QI 1 "general_operand" "qm")))]
622 ""
623 "movz%B0%L0 %1,%0")
624\f
625;;- sign extension instructions
626;; Note that the one starting from HImode comes before those for QImode
627;; so that a constant operand will match HImode, not QImode.
628
629/*
630(define_insn "extendsidi2"
631 [(set (match_operand:DI 0 "general_operand" "=a")
632 (sign_extend:DI
633 (match_operand:SI 1 "general_operand" "a")))]
634 ""
635 "clq")
636*/
637
638;; Note that the i386 programmers' manual says that the opcodes
639;; are named movsx..., but the assembler on Unix does not accept that.
640;; We use what the Unix assembler expects.
641
642(define_insn "extendhisi2"
643 [(set (match_operand:SI 0 "general_operand" "=r")
644 (sign_extend:SI
645 (match_operand:HI 1 "general_operand" "rm")))]
646 ""
647 "movs%W0%L0 %1,%0")
648
649(define_insn "extendqihi2"
650 [(set (match_operand:HI 0 "general_operand" "=r")
651 (sign_extend:HI
652 (match_operand:QI 1 "general_operand" "qm")))]
653 ""
654 "movs%B0%W0 %1,%0")
655
656(define_insn "extendqisi2"
657 [(set (match_operand:SI 0 "general_operand" "=r")
658 (sign_extend:SI
659 (match_operand:QI 1 "general_operand" "qm")))]
660 ""
661 "movs%B0%L0 %1,%0"
662 )
663\f
664;; Conversions between float and double.
665
666(define_insn "extendsfdf2"
667 [(set (match_operand:DF 0 "general_operand" "=fm,f,fm,fm")
668 (float_extend:DF
669 (match_operand:SF 1 "general_operand" "m,0,f,!*r")))]
670 "TARGET_80387"
671 "*
672{
673 if (FP_REG_P (operands[0]))
674 {
675 output_movsf (operands[0], operands[1]);
676 RET;
677 }
678 if (FP_REG_P (operands[1]))
679 {
680 if (top_dead_p (insn))
681 fp_pop_df (operands[0]);
682 else
683 fp_store_df (operands[0]);
684 RET;
685 }
686 output_movsf (FP_TOP, operands[1]);
687 fp_pop_df (operands[0]);
688 RETCOM (extendsfdf2);
689}")
690
691;; This cannot output into an f-reg because there is no way to be
692;; sure of truncating in that case.
693(define_insn "truncdfsf2"
694 [(set (match_operand:SF 0 "general_operand" "=m,!*r")
695 (float_truncate:SF
696 (match_operand:DF 1 "general_operand" "f,f")))]
697 "TARGET_80387"
698 "*
699{
700 if (top_dead_p (insn))
701 fp_pop_sf (operands[0]);
702 else
703 fp_store_sf (operands[0]);
704 RETCOM (truncdfsf2);
705}")
706\f
707;; Conversion between fixed point and floating point.
708;; Note that among the fix-to-float insns
709;; the ones that start with SImode come first.
710;; That is so that an operand that is a CONST_INT
711;; (and therefore lacks a specific machine mode).
712;; will be recognized as SImode (which is always valid)
713;; rather than as QImode or HImode. The 80387 would not know
714;; what to do with the smaller sizes anyway. (I think).
715
716(define_insn "floatsisf2"
717 [(set (match_operand:SF 0 "general_operand" "=fm,fm")
718 (float:SF (match_operand:SI 1 "general_operand" "m,!*r")))]
719 "TARGET_80387"
720 "*
721{
722/* fp_pop_level++; */
723
724 if (GET_CODE (operands[1]) != MEM)
725 {
726 rtx xops[2];
727 output_asm_insn (\"push%L0 %1\", operands);
728 operands[1] = AT_SP (SImode);
729 output_asm_insn (\"fild%L0 %1\", operands);
730 xops[0] = stack_pointer_rtx;
731 xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
732 output_asm_insn (AS2 (add%L0,%1,%0), xops);
733 }
734 else
735 output_asm_insn (\"fild%L0 %1\", operands);
736
737 if (! FP_REG_P (operands[0]))
738 {
739/* fp_pop_level--; */
740 return \"fstp%S0 %0\";
741 }
742 RET;
743}")
744
745(define_insn "floatsidf2"
746 [(set (match_operand:DF 0 "general_operand" "=fm,fm")
747 (float:DF (match_operand:SI 1 "general_operand" "m,!*r")))]
748 "TARGET_80387"
749 "*
750{
751/* fp_pop_level++; */
752 if (GET_CODE (operands[1]) != MEM)
753 {
754 rtx xops[2];
755 output_asm_insn (\"push%L0 %1\", operands);
756 operands[1] = AT_SP (SImode);
757 output_asm_insn (\"fild%L0 %1\", operands);
758 xops[0] = stack_pointer_rtx;
759 xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
760 output_asm_insn (AS2 (add%L0,%1,%0), xops);
761 }
762 else
763 output_asm_insn (\"fild%L0 %1\", operands);
764 if (! FP_REG_P (operands[0]))
765 {
766/* fp_pop_level--; */
767 return \"fstp%Q0 %0\";
768 }
769 RET;
770}")
771\f
772;; Convert a float to a float whose value is an integer.
773;; This is the first stage of converting it to an integer type.
774
775;; On the 387 truncating doub to an short integer shor can be performed:
776
777; fstcw -4(%esp) ;save cw
778; movw -4(%esp),%ax
779; orw $0x0c00,%ax ;set rounding to chop towards zero
780; movw %ax,-2(%esp) ;
781; fldcw -2(%esp) ;
782; fldl doubl
783; fistpl -12(%esp) ;store the round value
784; fldcw -4(%esp) ;restore cw
785; movl -12(%esp),%eax
786; movw %ax,shor ; move the result into shor.
787
788;; but it is probably better to have a call, rather than waste this
789;; space. The last instruction would have been a movl if were
790;; going to an int instead of a short.
791;; For the moment we will go with the soft float for these.
792
793/* These are incorrect since they don't set the rounding bits of CW flag.
794 The proper way to do that is to make the function prologue save the CW
795 and also construct the alternate CW value needed for these insns.
796 Then these insns can output two fldcw's, referring to fixed places in
797 the stack frame.
798
799;; Convert a float whose value is an integer
800;; to an actual integer. Second stage of converting float to integer type.
801
802(define_insn "fix_truncsfqi2"
803 [(set (match_operand:QI 0 "general_operand" "=m,?*q")
804 (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
805 "TARGET_80387"
806 "*
807{
808 fp_pop_int (operands[0]);
809 RET;
810}")
811
812(define_insn "fix_truncsfhi2"
813 [(set (match_operand:HI 0 "general_operand" "=m,?*r")
814 (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
815 "TARGET_80387"
816 "*
817{
818 fp_pop_int (operands[0]);
819 RET;
820}")
821
822(define_insn "fix_truncsfsi2"
823 [(set (match_operand:SI 0 "general_operand" "=m,?*r")
824 (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
825 "TARGET_80387"
826 "*
827{
828 fp_pop_int (operands[0]);
829 RET;
830}")
831
832(define_insn "fix_truncdfqi2"
833 [(set (match_operand:QI 0 "general_operand" "=m,?*q")
834 (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
835
836 "TARGET_80387"
837 "*
838{
839 fp_pop_int (operands[0]);
840 RET;
841}")
842
843
844(define_insn "fix_truncdfhi2"
845 [(set (match_operand:HI 0 "general_operand" "=m,?*r")
846 (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
847 "TARGET_80387"
848 "*
849{
850 fp_pop_int (operands[0]);
851 RET;
852}")
853
854
855(define_insn "fix_truncdfsi2"
856 [(set (match_operand:SI 0 "general_operand" "=m,?*r")
857 (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
858 "TARGET_80387"
859 "*
860{
861 fp_pop_int (operands[0]);
862 RET;
863}")
864*/
865
866\f
867;;- add instructions
868;;moved incl to above leal
869
870(define_insn "addsi3"
871 [(set (match_operand:SI 0 "general_operand" "=rm,r")
872 (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
873 (match_operand:SI 2 "general_operand" "ri,rm")))]
874 ""
875 "add%L0 %2,%0")
876
877(define_insn ""
878 [(set (match_operand:HI 0 "general_operand" "=g")
879 (plus:HI (match_operand:HI 1 "general_operand" "0")
880 (const_int 1)))]
881 ""
882 "inc%W0 %0")
883
884(define_insn "addhi3"
885 [(set (match_operand:HI 0 "general_operand" "=rm,r")
886 (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
887 (match_operand:HI 2 "general_operand" "ri,rm")))]
888 ""
889 "add%W0 %2,%0")
890
891(define_insn ""
892 [(set (match_operand:QI 0 "general_operand" "=qm")
893 (plus:QI (match_operand:QI 1 "general_operand" "0")
894 (const_int 1)))]
895 ""
896 "inc%B0 %0")
897
898(define_insn "addqi3"
899 [(set (match_operand:QI 0 "general_operand" "=m,q")
900 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
901 (match_operand:QI 2 "general_operand" "qn,qmn")))]
902 ""
903 "add%B0 %2,%0")
904
905;;had "fmF,m"
906
907(define_insn "adddf3"
908 [(set (match_operand:DF 0 "general_operand" "=f,m,f")
909 (plus:DF (match_operand:DF 1 "general_operand" "%0,0,0")
910 (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
911 "TARGET_80387"
912 "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")
913
914(define_insn "addsf3"
915 [(set (match_operand:SF 0 "general_operand" "=f,m,f")
916 (plus:SF (match_operand:SF 1 "general_operand" "%0,0,0")
917 (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
918 "TARGET_80387"
919 "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")
920\f
921;;- subtract instructions
922
923;;moved decl above leal
924
925(define_insn "subsi3"
926 [(set (match_operand:SI 0 "general_operand" "=rm,r")
927 (minus:SI (match_operand:SI 1 "general_operand" "0,0")
928 (match_operand:SI 2 "general_operand" "ri,rm")))]
929 ""
930 "sub%L0 %2,%0")
931
932(define_insn ""
933 [(set (match_operand:HI 0 "general_operand" "=g")
934 (minus:HI (match_operand:HI 1 "general_operand" "0")
935 (const_int 1)))]
936 ""
937 "dec%W0 %0")
938
939(define_insn "subhi3"
940 [(set (match_operand:HI 0 "general_operand" "=rm,r")
941 (minus:HI (match_operand:HI 1 "general_operand" "0,0")
942 (match_operand:HI 2 "general_operand" "ri,rm")))]
943 ""
944 "sub%W0 %2,%0")
945
946(define_insn ""
947 [(set (match_operand:QI 0 "general_operand" "=qm")
948 (minus:QI (match_operand:QI 1 "general_operand" "0")
949 (const_int 1)))]
950 ""
951 "dec%B0 %0")
952
953(define_insn "subqi3"
954 [(set (match_operand:QI 0 "general_operand" "=m,q")
955 (minus:QI (match_operand:QI 1 "general_operand" "0,0")
956 (match_operand:QI 2 "general_operand" "qn,qmn")))]
957 ""
958 "sub%B0 %2,%0")
959
960(define_insn "subdf3"
961 [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
962 (minus:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
963 (match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
964 "TARGET_80387"
965 "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")
966
967
968(define_insn "subsf3"
969 [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
970 (minus:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
971 (match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
972 "TARGET_80387"
973 "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")
974\f
975;;- multiply instructions
976
977;(define_insn "mulqi3"
978; [(set (match_operand:QI 0 "general_operand" "=a")
979; (mult:QI (match_operand:QI 1 "general_operand" "%0")
980; (match_operand:QI 2 "general_operand" "qm")))]
981; ""
982; "mul%B0 %2,%0")
983
984(define_insn "mulhi3"
985 [(set (match_operand:HI 0 "general_operand" "=r,r")
986 (mult:SI (match_operand:HI 1 "general_operand" "%0,rm")
987 (match_operand:HI 2 "general_operand" "g,i")))]
988 ""
989 "*
990{
991 if (GET_CODE (operands[1]) == REG
992 && REGNO (operands[1]) == REGNO (operands[0])
993 && (GET_CODE (operands[2]) == MEM
994 || GET_CODE (operands[2]) == REG))
995 /* Assembler has weird restrictions. */
996 return AS2 (imul%W0,%2,%0);
997 return AS3 (imul%W0,%2,%1,%0);
998}")
999
1000(define_insn "mulsi3"
1001 [(set (match_operand:SI 0 "general_operand" "=r,r")
1002 (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
1003 (match_operand:SI 2 "general_operand" "g,i")))]
1004 ""
1005 "*
1006{
1007 if (GET_CODE (operands[1]) == REG
1008 && REGNO (operands[1]) == REGNO (operands[0])
1009 && (GET_CODE (operands[2]) == MEM
1010 || GET_CODE (operands[2]) == REG))
1011 /* Assembler has weird restrictions. */
1012 return AS2 (imul%L0,%2,%0);
1013 return AS3 (imul%L0,%2,%1,%0);
1014}")
1015
1016;; Turned off due to possible assembler bug.
1017;(define_insn "umulqi3"
1018; [(set (match_operand:QI 0 "general_operand" "=a")
1019; (umult:QI (match_operand:QI 1 "general_operand" "%0")
1020; (match_operand:QI 2 "general_operand" "qm")))]
1021; ""
1022; "mul%B0 %2,%0")
1023
1024;(define_insn "umulqihi3"
1025; [(set (match_operand:HI 0 "general_operand" "=a")
1026; (umult:HI (match_operand:QI 1 "general_operand" "%0")
1027; (match_operand:QI 2 "general_operand" "qm")))]
1028; ""
1029; "mul%B0 %2,%0")
1030
1031(define_insn "umulhi3"
1032 [(set (match_operand:HI 0 "general_operand" "=a")
1033 (umult:SI (match_operand:HI 1 "general_operand" "%0")
1034 (match_operand:HI 2 "general_operand" "rm")))
1035 (clobber (reg:HI 1))]
1036 ""
1037 "mul%W0 %2,%0")
1038
1039(define_insn "umulsi3"
1040 [(set (match_operand:SI 0 "general_operand" "=a")
1041 (umult:SI (match_operand:SI 1 "general_operand" "%0")
1042 (match_operand:SI 2 "general_operand" "rm")))
1043 (clobber (reg:SI 1))]
1044 ""
1045 "mul%L0 %2,%0")
1046
1047(define_insn "muldf3"
1048 [(set (match_operand:DF 0 "general_operand" "=f,m,f")
1049 (mult:DF (match_operand:DF 1 "general_operand" "%0,0,0")
1050 (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
1051 "TARGET_80387"
1052 "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
1053")
1054
1055(define_insn "mulsf3"
1056 [(set (match_operand:SF 0 "general_operand" "=f,m,f")
1057 (mult:SF (match_operand:SF 1 "general_operand" "%0,0,0")
1058 (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
1059 "TARGET_80387"
1060 "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
1061")
1062\f
1063;;- divide instructions
1064(define_insn "divdf3"
1065 [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
1066 (div:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
1067 (match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
1068 "TARGET_80387"
1069 "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
1070")
1071
1072(define_insn "divsf3"
1073 [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
1074 (div:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
1075 (match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
1076 "TARGET_80387"
1077 "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
1078")
1079\f
1080;; Remainder instructions.
1081
1082(define_insn "divmodsi4"
1083 [(set (match_operand:SI 0 "general_operand" "=a")
1084 (div:SI (match_operand:SI 1 "general_operand" "0")
1085 (match_operand:SI 2 "general_operand" "rm")))
1086 (set (match_operand:SI 3 "general_operand" "=&d")
1087 (mod:SI (match_dup 1) (match_dup 2)))]
1088 ""
1089 "cltd\;idiv%L0 %2")
1090
1091(define_insn "udivmodsi4"
1092 [(set (match_operand:SI 0 "general_operand" "=a")
1093 (udiv:SI (match_operand:SI 1 "general_operand" "0")
1094 (match_operand:SI 2 "general_operand" "rm")))
1095 (set (match_operand:SI 3 "general_operand" "=&d")
1096 (umod:SI (match_dup 1) (match_dup 2)))]
1097 ""
1098 "xor%L0 %3,%3\;div%L0 %2")
1099
1100/*
1101;;this should be a valid double division which we may want to add
1102
1103(define_insn ""
1104 [(set (match_operand:SI 0 "general_operand" "=a")
1105 (udiv:DI (match_operand:DI 1 "general_operand" "a")
1106 (match_operand:SI 2 "general_operand" "rm")))
1107 (set (match_operand:SI 3 "general_operand" "=d")
1108 (umod:SI (match_dup 1) (match_dup 2)))]
1109 ""
1110 "div%L0 %2,%0")
1111*/
1112\f
1113;;- and instructions
1114
1115;; The `r' in `rm' for operand 3 looks redundant, but it causes
1116;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
1117
1118(define_insn "andsi3"
1119 [(set (match_operand:SI 0 "general_operand" "=rm,r")
1120 (and:SI (match_operand:SI 1 "general_operand" "%0,0")
1121 (match_operand:SI 2 "general_operand" "ri,rm")))]
1122 ""
1123 "and%L0 %2,%0")
1124
1125(define_insn "andhi3"
1126 [(set (match_operand:HI 0 "general_operand" "=rm,r")
1127 (and:HI (match_operand:HI 1 "general_operand" "%0,0")
1128 (match_operand:HI 2 "general_operand" "ri,rm")))]
1129 ""
1130 "and%W0 %2,%0")
1131
1132(define_insn "andqi3"
1133 [(set (match_operand:QI 0 "general_operand" "=m,q")
1134 (and:QI (match_operand:QI 1 "general_operand" "%0,0")
1135 (match_operand:QI 2 "general_operand" "qn,qmn")))]
1136 ""
1137 "and%B0 %2,%0")
1138
1139/* I am nervous about these two.. add them later..
1140;I presume this means that we have something in say op0= eax which is small
1141;and we want to and it with memory so we can do this by just an
1142;andb m,%al and have success.
1143(define_insn ""
1144 [(set (match_operand:SI 0 "general_operand" "=r")
1145 (and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rm"))
1146 (match_operand:SI 2 "general_operand" "0")))]
1147 "GET_CODE (operands[2]) == CONST_INT
1148 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
1149 "and%W0 %1,%0")
1150
1151(define_insn ""
1152 [(set (match_operand:SI 0 "general_operand" "=q")
1153 (and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "qm"))
1154 (match_operand:SI 2 "general_operand" "0")))]
1155 "GET_CODE (operands[2]) == CONST_INT
1156 && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
1157 "and%L0 %1,%0")
1158
1159*/
1160
1161
1162\f
1163;;- Bit set (inclusive or) instructions
1164
1165(define_insn "iorsi3"
1166 [(set (match_operand:SI 0 "general_operand" "=rm,r")
1167 (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
1168 (match_operand:SI 2 "general_operand" "ri,rm")))]
1169 ""
1170 "or%L0 %2,%0")
1171
1172(define_insn "iorhi3"
1173 [(set (match_operand:HI 0 "general_operand" "=rm,r")
1174 (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
1175 (match_operand:HI 2 "general_operand" "ri,rm")))]
1176 ""
1177 "or%W0 %2,%0")
1178
1179(define_insn "iorqi3"
1180 [(set (match_operand:QI 0 "general_operand" "=m,q")
1181 (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
1182 (match_operand:QI 2 "general_operand" "qn,qmn")))]
1183 ""
1184 "or%B0 %2,%0")
1185\f
1186;;- xor instructions
1187
1188(define_insn "xorsi3"
1189 [(set (match_operand:SI 0 "general_operand" "=rm,r")
1190 (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
1191 (match_operand:SI 2 "general_operand" "ri,rm")))]
1192 ""
1193 "xor%L0 %2,%0")
1194
1195(define_insn "xorhi3"
1196 [(set (match_operand:HI 0 "general_operand" "=rm,r")
1197 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1198 (match_operand:HI 2 "general_operand" "ri,rm")))]
1199 ""
1200 "xor%W0 %2,%0")
1201
1202(define_insn "xorqi3"
1203 [(set (match_operand:QI 0 "general_operand" "=qm")
1204 (xor:QI (match_operand:QI 1 "general_operand" "%0")
1205 (match_operand:QI 2 "general_operand" "qn")))]
1206 ""
1207 "xor%B0 %2,%0")
1208\f
1209;;- negation instructions
1210(define_insn "negsi2"
1211 [(set (match_operand:SI 0 "general_operand" "=rm")
1212 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1213 ""
1214 "neg%L0 %0")
1215
1216(define_insn "neghi2"
1217 [(set (match_operand:HI 0 "general_operand" "=rm")
1218 (neg:HI (match_operand:HI 1 "general_operand" "0")))]
1219 ""
1220 "neg%W0 %0")
1221
1222(define_insn "negqi2"
1223 [(set (match_operand:QI 0 "general_operand" "=qm")
1224 (neg:QI (match_operand:QI 1 "general_operand" "0")))]
1225 ""
1226 "neg%B0 %0")
1227
1228(define_insn "negsf2"
1229 [(set (match_operand:SF 0 "general_operand" "=f,!m")
1230 (neg:SF (match_operand:SF 1 "general_operand" "0,0")))]
1231 "TARGET_80387"
1232 "*FP_CALL1 (\"fchs\")")
1233
1234(define_insn "negdf2"
1235 [(set (match_operand:DF 0 "general_operand" "=f,!m")
1236 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1237 "TARGET_80387"
1238 "*FP_CALL1 (\"fchs\")")
1239\f
1240;; Absolute value instructions
1241
1242(define_insn "abssf2"
1243 [(set (match_operand:SF 0 "general_operand" "=f,!m")
1244 (abs:SF (match_operand:SF 1 "general_operand" "0,0")))]
1245 "TARGET_80387"
1246 "*FP_CALL1 (\"fabs\")")
1247
1248(define_insn "absdf2"
1249 [(set (match_operand:DF 0 "general_operand" "=f,!m")
1250 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1251 "TARGET_80387"
1252 "*FP_CALL1 (\"fabs\")")
1253\f
1254;;- one complement instructions
1255(define_insn "one_cmplsi2"
1256 [(set (match_operand:SI 0 "general_operand" "=rm")
1257 (not:SI (match_operand:SI 1 "general_operand" "0")))]
1258 ""
1259 "not%L0 %0")
1260
1261(define_insn "one_cmplhi2"
1262 [(set (match_operand:HI 0 "general_operand" "=rm")
1263 (not:HI (match_operand:HI 1 "general_operand" "0")))]
1264 ""
1265 "not%W0 %0")
1266
1267(define_insn "one_cmplqi2"
1268 [(set (match_operand:QI 0 "general_operand" "=qm")
1269 (not:QI (match_operand:QI 1 "general_operand" "0")))]
1270 ""
1271 "not%B0 %0")
1272\f
1273;;- arithmetic shift instructions
1274
1275(define_insn "ashlsi3"
1276 [(set (match_operand:SI 0 "general_operand" "=rm")
1277 (ashift:SI (match_operand:SI 1 "general_operand" "0")
1278 (match_operand:SI 2 "general_operand" "cI")))]
1279 ""
1280 "*
1281{
1282 if (REG_P (operands[2]))
1283 return AS2 (sal%L0,%R0cl,%0);
1284 else if (REG_P (operands[1]) && GET_CODE (operands[2]) == CONST_INT
1285 && INTVAL (operands[2]) == 1)
1286 return AS2 (add%L0,%1,%1);
1287 return AS2 (sal%L0,%2,%1);
1288}")
1289
1290(define_insn "ashlhi3"
1291 [(set (match_operand:HI 0 "general_operand" "=rm")
1292 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1293 (match_operand:HI 2 "general_operand" "cI")))]
1294 ""
1295 "*
1296{
1297 if (REG_P (operands[2]))
1298 return AS2 (sal%W0,%R0cl,%0);
1299 else
1300 return AS2 (sal%W0,%2,%1);
1301}")
1302
1303(define_insn "ashlqi3"
1304 [(set (match_operand:QI 0 "general_operand" "=qm")
1305 (ashift:QI (match_operand:QI 1 "general_operand" "0")
1306 (match_operand:QI 2 "general_operand" "cI")))]
1307 ""
1308 "*
1309{
1310 if (REG_P (operands[2]))
1311 return AS2 (sal%B0,%R0cl,%0);
1312 else
1313 return AS2 (sal%B0,%2,%1);
1314}")
1315
1316(define_insn "ashrsi3"
1317 [(set (match_operand:SI 0 "general_operand" "=rm")
1318 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
1319 (match_operand:SI 2 "general_operand" "cI")))]
1320 ""
1321 "*
1322{
1323 if (REG_P (operands[2]))
1324 return AS2 (sar%L0,%R0cl,%0);
1325 else
1326 return AS2 (sar%L0,%2,%0);
1327}")
1328
1329(define_insn "ashrhi3"
1330 [(set (match_operand:HI 0 "general_operand" "=rm")
1331 (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
1332 (match_operand:HI 2 "general_operand" "cI")))]
1333 ""
1334 "*
1335{
1336 if (REG_P (operands[2]))
1337 return AS2 (sar%W0,%R0cl,%0);
1338 else
1339 return AS2 (sar%W0,%2,%0);
1340}")
1341
1342(define_insn "ashrqi3"
1343 [(set (match_operand:QI 0 "general_operand" "=qm")
1344 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
1345 (match_operand:QI 2 "general_operand" "cI")))]
1346 ""
1347 "*
1348{
1349 if (REG_P (operands[2]))
1350 return AS2 (sar%B0,%R0cl,%0);
1351 return
1352 AS2 (sar%B0,%2,%1);
1353}")
1354\f
1355;;- logical shift instructions
1356
1357(define_insn "lshlsi3"
1358 [(set (match_operand:SI 0 "general_operand" "=rm")
1359 (lshift:SI (match_operand:SI 1 "general_operand" "0")
1360 (match_operand:SI 2 "general_operand" "cI")))]
1361 ""
1362 "*
1363{
1364 if (REG_P (operands[2]))
1365 return AS2 (shl%L0,%R0cl,%0);
1366 else
1367 return AS2 (shl%L0,%2,%1);
1368}")
1369
1370(define_insn "lshlhi3"
1371 [(set (match_operand:HI 0 "general_operand" "=rm")
1372 (lshift:HI (match_operand:HI 1 "general_operand" "0")
1373 (match_operand:HI 2 "general_operand" "cI")))]
1374 ""
1375 "*
1376{
1377 if (REG_P (operands[2]))
1378 return AS2 (shl%W0,%R0cl,%0);
1379 else
1380 return AS2 (shl%W0,%2,%1);
1381}")
1382
1383(define_insn "lshlqi3"
1384 [(set (match_operand:QI 0 "general_operand" "=qm")
1385 (lshift:QI (match_operand:QI 1 "general_operand" "0")
1386 (match_operand:QI 2 "general_operand" "cI")))]
1387 ""
1388 "*
1389{
1390 if (REG_P (operands[2]))
1391 return AS2 (shl%B0,%R0cl,%0);
1392 else
1393 return AS2 (shl%B0,%2,%1);
1394}")
1395
1396(define_insn "lshrsi3"
1397 [(set (match_operand:SI 0 "general_operand" "=rm")
1398 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1399 (match_operand:SI 2 "general_operand" "cI")))]
1400 ""
1401 "*
1402{
1403 if (REG_P (operands[2]))
1404 return AS2 (shr%L0,%R0cl,%0);
1405 else
1406 return AS2 (shr%L0,%2,%1);
1407}")
1408
1409(define_insn "lshrhi3"
1410 [(set (match_operand:HI 0 "general_operand" "=rm")
1411 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
1412 (match_operand:HI 2 "general_operand" "cI")))]
1413 ""
1414 "*
1415{
1416 if (REG_P (operands[2]))
1417 return AS2 (shr%W0,%%cl,%0);
1418 else
1419 return AS2 (shr%W0,%2,%1);
1420}")
1421
1422(define_insn "lshrqi3"
1423 [(set (match_operand:QI 0 "general_operand" "=qm")
1424 (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
1425 (match_operand:QI 2 "general_operand" "cI")))]
1426 ""
1427 "*
1428{
1429 if (REG_P (operands[2]))
1430 return AS2 (shr%B0,%%cl,%0);
1431 else
1432 return AS2 (shr%B0,%2,%1);
1433}")
1434\f
1435;;- rotate instructions
1436
1437(define_insn "rotlsi3"
1438 [(set (match_operand:SI 0 "general_operand" "=rm")
1439 (rotate:SI (match_operand:SI 1 "general_operand" "0")
1440 (match_operand:SI 2 "general_operand" "cI")))]
1441 ""
1442 "*
1443{
1444 if (REG_P (operands[2]))
1445 return AS2 (rol%L0,%%cl,%0);
1446 else
1447 return AS2 (rol%L0,%2,%1);
1448}")
1449
1450(define_insn "rotlhi3"
1451 [(set (match_operand:HI 0 "general_operand" "=rm")
1452 (rotate:HI (match_operand:HI 1 "general_operand" "0")
1453 (match_operand:HI 2 "general_operand" "cI")))]
1454 ""
1455 "*
1456{
1457 if (REG_P (operands[2]))
1458 return AS2 (rol%W0,%%cl,%0);
1459 else
1460 return AS2 (rol%W0,%2,%1);
1461}")
1462
1463(define_insn "rotlqi3"
1464 [(set (match_operand:QI 0 "general_operand" "=qm")
1465 (rotate:QI (match_operand:QI 1 "general_operand" "0")
1466 (match_operand:QI 2 "general_operand" "cI")))]
1467 ""
1468 "*
1469{
1470 if (REG_P (operands[2]))
1471 return AS2 (rol%B0,%%cl,%0);
1472 else
1473 return AS2 (rol%B0,%2,%1);
1474}")
1475
1476(define_insn "rotrsi3"
1477 [(set (match_operand:SI 0 "general_operand" "=rm")
1478 (rotatert:SI (match_operand:SI 1 "general_operand" "0")
1479 (match_operand:SI 2 "general_operand" "cI")))]
1480 ""
1481 "*
1482{
1483 if (REG_P (operands[2]))
1484 return AS2 (ror%L0,%%cl,%0);
1485 else
1486 return AS2 (ror%L0,%2,%1);
1487}")
1488
1489(define_insn "rotrhi3"
1490 [(set (match_operand:HI 0 "general_operand" "=rm")
1491 (rotatert:HI (match_operand:HI 1 "general_operand" "0")
1492 (match_operand:HI 2 "general_operand" "cI")))]
1493 ""
1494 "*
1495{
1496 if (REG_P (operands[2]))
1497 return AS2 (ror%W0,%%cl,%0);
1498 else
1499 return AS2 (ror%W0,%2,%1);
1500}")
1501
1502(define_insn "rotrqi3"
1503 [(set (match_operand:QI 0 "general_operand" "=qm")
1504 (rotatert:QI (match_operand:QI 1 "general_operand" "0")
1505 (match_operand:QI 2 "general_operand" "cI")))]
1506 ""
1507 "*
1508{
1509 if (REG_P (operands[2]))
1510 return AS2 (ror%B0,%%cl,%0);
1511 else
1512 return AS2 (ror%B0,%2,%1);
1513}")
1514\f
1515;; Store-flag instructions.
1516
1517(define_insn "seq"
1518 [(set (match_operand:QI 0 "general_operand" "=q")
1519 (eq (cc0) (const_int 0)))]
1520 ""
1521 "*
1522 cc_status = cc_prev_status;
1523 return \"sete %0\";
1524")
1525
1526(define_insn "sne"
1527 [(set (match_operand:QI 0 "general_operand" "=q")
1528 (ne (cc0) (const_int 0)))]
1529 ""
1530 "*
1531 cc_status = cc_prev_status;
1532 return \"setne %0\";
1533")
1534
1535(define_insn "sgt"
1536 [(set (match_operand:QI 0 "general_operand" "=q")
1537 (gt (cc0) (const_int 0)))]
1538 ""
1539 "*
1540 cc_status = cc_prev_status;
1541 OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0);
1542")
1543
1544(define_insn "sgtu"
1545 [(set (match_operand:QI 0 "general_operand" "=q")
1546 (gtu (cc0) (const_int 0)))]
1547 ""
1548 "* cc_status = cc_prev_status;
1549 return \"seta %0\"; ")
1550
1551(define_insn "slt"
1552 [(set (match_operand:QI 0 "general_operand" "=q")
1553 (lt (cc0) (const_int 0)))]
1554 ""
1555 "* cc_status = cc_prev_status;
1556 OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ")
1557
1558(define_insn "sltu"
1559 [(set (match_operand:QI 0 "general_operand" "=q")
1560 (ltu (cc0) (const_int 0)))]
1561 ""
1562 "* cc_status = cc_prev_status;
1563 return \"setb %0\"; ")
1564
1565(define_insn "sge"
1566 [(set (match_operand:QI 0 "general_operand" "=q")
1567 (ge (cc0) (const_int 0)))]
1568 ""
1569 "* cc_status = cc_prev_status;
1570 OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ")
1571
1572(define_insn "sgeu"
1573 [(set (match_operand:QI 0 "general_operand" "=q")
1574 (geu (cc0) (const_int 0)))]
1575 ""
1576 "* cc_status = cc_prev_status;
1577 return \"setae %0\"; ")
1578
1579(define_insn "sle"
1580 [(set (match_operand:QI 0 "general_operand" "=q")
1581 (le (cc0) (const_int 0)))]
1582 ""
1583 "*
1584 cc_status = cc_prev_status;
1585 OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0);
1586")
1587
1588(define_insn "sleu"
1589 [(set (match_operand:QI 0 "general_operand" "=q")
1590 (leu (cc0) (const_int 0)))]
1591 ""
1592 "* cc_status = cc_prev_status;
1593 return \"setbe %0\"; ")
1594\f
1595;; Basic conditional jump instructions.
1596;; We ignore the overflow flag for signed branch instructions.
1597
1598(define_insn "beq"
1599 [(set (pc)
1600 (if_then_else (eq (cc0)
1601 (const_int 0))
1602 (label_ref (match_operand 0 "" ""))
1603 (pc)))]
1604 ""
1605 "je %l0")
1606
1607(define_insn "bne"
1608 [(set (pc)
1609 (if_then_else (ne (cc0)
1610 (const_int 0))
1611 (label_ref (match_operand 0 "" ""))
1612 (pc)))]
1613 ""
1614 "jne %l0")
1615
1616(define_insn "bgt"
1617 [(set (pc)
1618 (if_then_else (gt (cc0)
1619 (const_int 0))
1620 (label_ref (match_operand 0 "" ""))
1621 (pc)))]
1622 ""
1623 "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
1624
1625(define_insn "bgtu"
1626 [(set (pc)
1627 (if_then_else (gtu (cc0)
1628 (const_int 0))
1629 (label_ref (match_operand 0 "" ""))
1630 (pc)))]
1631 ""
1632 "ja %l0")
1633
1634;; There is no jump insn to check for `<' on IEEE floats.
1635;; Page 17-80 in the 80387 manual says jb, but that's wrong;
1636;; jb checks for `not >='. So swap the operands and do `>'.
1637(define_expand "blt"
1638 [(set (pc)
1639 (if_then_else (lt (cc0)
1640 (const_int 0))
1641 (label_ref (match_operand 0 "" ""))
1642 (pc)))]
1643 ""
1644 "
1645{
1646 extern rtx sequence_stack;
1647 rtx prev = XEXP (XEXP (sequence_stack, 1), 0);
1648 rtx body = PATTERN (prev);
1649 rtx comp;
1650 if (GET_CODE (body) == SET)
1651 comp = SET_SRC (body);
1652 else
1653 comp = SET_SRC (XVECEXP (body, 0, 0));
1654
1655 if (GET_CODE (comp) == COMPARE
1656 ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
1657 : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
1658 {
1659 if (GET_CODE (comp) == COMPARE)
1660 {
1661 rtx op0 = XEXP (comp, 0);
1662 rtx op1 = XEXP (comp, 1);
1663 XEXP (comp, 0) = op1;
1664 XEXP (comp, 1) = op0;
1665 }
1666 else
1667 {
1668 rtx new = gen_rtx (COMPARE, VOIDmode,
1669 CONST0_RTX (GET_MODE (comp)), comp);
1670 if (GET_CODE (body) == SET)
1671 SET_SRC (body) = new;
1672 else
1673 SET_SRC (XVECEXP (body, 0, 0)) = new;
1674 }
1675 emit_insn (gen_bgt (operands[0]));
1676 DONE;
1677 }
1678}")
1679
1680(define_insn ""
1681 [(set (pc)
1682 (if_then_else (lt (cc0)
1683 (const_int 0))
1684 (label_ref (match_operand 0 "" ""))
1685 (pc)))]
1686 ""
1687 "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
1688
1689(define_insn "bltu"
1690 [(set (pc)
1691 (if_then_else (ltu (cc0)
1692 (const_int 0))
1693 (label_ref (match_operand 0 "" ""))
1694 (pc)))]
1695 ""
1696 "jb %l0")
1697
1698(define_insn "bge"
1699 [(set (pc)
1700 (if_then_else (ge (cc0)
1701 (const_int 0))
1702 (label_ref (match_operand 0 "" ""))
1703 (pc)))]
1704 ""
1705 "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")")
1706
1707(define_insn "bgeu"
1708 [(set (pc)
1709 (if_then_else (geu (cc0)
1710 (const_int 0))
1711 (label_ref (match_operand 0 "" ""))
1712 (pc)))]
1713 ""
1714 "jae %l0")
1715
1716;; See comment on `blt', above.
1717(define_expand "ble"
1718 [(set (pc)
1719 (if_then_else (le (cc0)
1720 (const_int 0))
1721 (label_ref (match_operand 0 "" ""))
1722 (pc)))]
1723 ""
1724 "
1725{
1726 extern rtx sequence_stack;
1727 rtx prev = XEXP (XEXP (sequence_stack, 1), 0);
1728 rtx body = PATTERN (prev);
1729 rtx comp;
1730 if (GET_CODE (body) == SET)
1731 comp = SET_SRC (body);
1732 else
1733 comp = SET_SRC (XVECEXP (body, 0, 0));
1734
1735 if (GET_CODE (comp) == COMPARE
1736 ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
1737 : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
1738 {
1739 if (GET_CODE (comp) == COMPARE)
1740 {
1741 rtx op0 = XEXP (comp, 0);
1742 rtx op1 = XEXP (comp, 1);
1743 XEXP (comp, 0) = op1;
1744 XEXP (comp, 1) = op0;
1745 }
1746 else
1747 {
1748 rtx new = gen_rtx (COMPARE, VOIDmode,
1749 CONST0_RTX (GET_MODE (comp)), comp);
1750 if (GET_CODE (body) == SET)
1751 SET_SRC (body) = new;
1752 else
1753 SET_SRC (XVECEXP (body, 0, 0)) = new;
1754 }
1755 emit_insn (gen_bge (operands[0]));
1756 DONE;
1757 }
1758}")
1759
1760(define_insn ""
1761 [(set (pc)
1762 (if_then_else (le (cc0)
1763 (const_int 0))
1764 (label_ref (match_operand 0 "" ""))
1765 (pc)))]
1766 ""
1767 "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
1768
1769(define_insn "bleu"
1770 [(set (pc)
1771 (if_then_else (leu (cc0)
1772 (const_int 0))
1773 (label_ref (match_operand 0 "" ""))
1774 (pc)))]
1775 ""
1776 "jbe %l0")
1777\f
1778;; Negated conditional jump instructions.
1779
1780(define_insn ""
1781 [(set (pc)
1782 (if_then_else (eq (cc0)
1783 (const_int 0))
1784 (pc)
1785 (label_ref (match_operand 0 "" ""))))]
1786 ""
1787 "jne %l0")
1788
1789(define_insn ""
1790 [(set (pc)
1791 (if_then_else (ne (cc0)
1792 (const_int 0))
1793 (pc)
1794 (label_ref (match_operand 0 "" ""))))]
1795 ""
1796 "je %l0")
1797
1798(define_insn ""
1799 [(set (pc)
1800 (if_then_else (gt (cc0)
1801 (const_int 0))
1802 (pc)
1803 (label_ref (match_operand 0 "" ""))))]
1804 ""
1805 "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
1806
1807(define_insn ""
1808 [(set (pc)
1809 (if_then_else (gtu (cc0)
1810 (const_int 0))
1811 (pc)
1812 (label_ref (match_operand 0 "" ""))))]
1813 ""
1814 "jbe %l0")
1815
1816(define_insn ""
1817 [(set (pc)
1818 (if_then_else (lt (cc0)
1819 (const_int 0))
1820 (pc)
1821 (label_ref (match_operand 0 "" ""))))]
1822 ""
1823 "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")
1824")
1825
1826(define_insn ""
1827 [(set (pc)
1828 (if_then_else (ltu (cc0)
1829 (const_int 0))
1830 (pc)
1831 (label_ref (match_operand 0 "" ""))))]
1832 ""
1833 "jae %l0")
1834
1835(define_insn ""
1836 [(set (pc)
1837 (if_then_else (ge (cc0)
1838 (const_int 0))
1839 (pc)
1840 (label_ref (match_operand 0 "" ""))))]
1841 ""
1842 "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
1843
1844(define_insn ""
1845 [(set (pc)
1846 (if_then_else (geu (cc0)
1847 (const_int 0))
1848 (pc)
1849 (label_ref (match_operand 0 "" ""))))]
1850 ""
1851 "jb %l0")
1852
1853(define_insn ""
1854 [(set (pc)
1855 (if_then_else (le (cc0)
1856 (const_int 0))
1857 (pc)
1858 (label_ref (match_operand 0 "" ""))))]
1859 ""
1860 "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
1861
1862(define_insn ""
1863 [(set (pc)
1864 (if_then_else (leu (cc0)
1865 (const_int 0))
1866 (pc)
1867 (label_ref (match_operand 0 "" ""))))]
1868 ""
1869 "ja %l0")
1870\f
1871;; Unconditional and other jump instructions
1872(define_insn "jump"
1873 [(set (pc)
1874 (label_ref (match_operand 0 "" "")))]
1875 ""
1876 "jmp %l0")
1877
1878(define_insn "tablejump"
1879 [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
1880 (use (label_ref (match_operand 1 "" "")))]
1881 ""
1882 "*
1883{
1884 CC_STATUS_INIT;
1885
1886 return \"jmp %*%0\";
1887}")
1888
1889/*
1890(define_insn ""
1891 [(set (pc)
1892 (if_then_else
1893 (ne (compare (minus:HI (match_operand:HI 0 "general_operand" "c")
1894 (const_int 1))
1895 (const_int -1))
1896 (const_int 0))
1897 (label_ref (match_operand 1 "" "g"))
1898 (pc)))
1899 (set (match_dup 0)
1900 (minus:HI (match_dup 0)
1901 (const_int 1)))]
1902 ""
1903 "loop %l1")
1904
1905(define_insn ""
1906 [(set (pc)
1907 (if_then_else
1908 (ne (compare (const_int -1)
1909 (minus:SI (match_operand:SI 0 "general_operand" "c")
1910 (const_int 1)))
1911 (const_int 0))
1912 (label_ref (match_operand 1 "" "g"))
1913 (pc)))
1914 (set (match_dup 0)
1915 (minus:SI (match_dup 0)
1916 (const_int 1)))]
1917 ""
1918 "loop %l1")
1919*/
1920
1921;; Call subroutine returning no value.
1922(define_insn "call"
1923 [(call (match_operand:QI 0 "indirect_operand" "m")
1924 (match_operand:SI 1 "general_operand" "g"))]
1925 ;; Operand 1 not really used on the m68000.
1926 ""
1927 "*
1928{
1929 if (GET_CODE (operands[0]) == MEM
1930 && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1931 {
1932 operands[0] = XEXP (operands[0], 0);
1933 return \"call %*%0\";
1934 }
1935 else
1936 return \"call %0\";
1937}")
1938
1939;; Call subroutine, returning value in operand 0
1940;; (which must be a hard register).
1941(define_insn "call_value"
1942 [(set (match_operand 0 "" "=rf")
1943 (call (match_operand:QI 1 "indirect_operand" "m")
1944 (match_operand:SI 2 "general_operand" "g")))]
1945 ;; Operand 2 not really used on the m68000.
1946 ""
1947 "*
1948{
1949 if (GET_CODE (operands[1]) == MEM
1950 && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1951 {
1952 operands[1] = XEXP (operands[1], 0);
1953 output_asm_insn (\"call %*%1\", operands);
1954 }
1955 else
1956 output_asm_insn (\"call %1\", operands);
1957
1958 if (GET_MODE (operands[0]) == DFmode
1959 || GET_MODE (operands[0]) == SFmode)
1960 {
1961/* fp_pop_level++; */
1962 /* pop if reg dead */
1963 if (!FP_REG_P (operands[0]))
1964 abort ();
1965 if (top_dead_p (insn))
1966 {
1967 POP_ONE_FP;
1968 }
1969 }
1970 RET;
1971}")
1972
1973(define_insn "nop"
1974 [(const_int 0)]
1975 ""
1976 "nop")
1977\f
1978;;- Local variables:
1979;;- mode:emacs-lisp
1980;;- comment-start: ";;- "
1981;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
1982;;- eval: (modify-syntax-entry ?[ "(]")
1983;;- eval: (modify-syntax-entry ?] ")[")
1984;;- eval: (modify-syntax-entry ?{ "(}")
1985;;- eval: (modify-syntax-entry ?} "){")
1986;;- End: