1;;- Machine description for Intel 860 chip for GNU C compiler
2;;   Copyright (C) 1989, 1990, 1997 Free Software Foundation, Inc.
3
4;; This file is part of GNU CC.
5
6;; GNU CC is free software; you can redistribute it and/or modify
7;; it under the terms of the GNU General Public License as published by
8;; the Free Software Foundation; either version 2, or (at your option)
9;; any later version.
10
11;; GNU CC is distributed in the hope that it will be useful,
12;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;; GNU General Public License for more details.
15
16;; You should have received a copy of the GNU General Public License
17;; along with GNU CC; see the file COPYING.  If not, write to
18;; the Free Software Foundation, 59 Temple Place - Suite 330,
19;; Boston, MA 02111-1307, USA.
20
21
22;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23
24;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
25;;- updates for most instructions.
26
27;;- Operand classes for the register allocator:
28
29/* Bit-test instructions.  */
30
31(define_insn ""
32  [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
33			  (match_operand:SI 1 "logic_operand" "rL"))
34		  (const_int 0)))]
35  ""
36  "*
37{
38  CC_STATUS_PARTIAL_INIT;
39  return \"and %1,%0,%?r0\";
40}")
41
42(define_insn ""
43  [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
44			  (match_operand:SI 1 "logic_operand" "rL"))
45		  (const_int 0)))]
46  ""
47  "*
48{
49  CC_STATUS_PARTIAL_INIT;
50  cc_status.flags |= CC_NEGATED;
51  return \"and %1,%0,%?r0\";
52}")
53
54(define_insn ""
55  [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
56			  (match_operand:SI 1 "immediate_operand" "i"))
57		  (const_int 0)))]
58  "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
59  "*
60{
61  CC_STATUS_PARTIAL_INIT;
62  return \"andh %H1,%0,%?r0\";
63}")
64
65(define_insn ""
66  [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
67			  (match_operand:SI 1 "immediate_operand" "i"))
68		  (const_int 0)))]
69  "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
70  "*
71{
72  CC_STATUS_PARTIAL_INIT;
73  cc_status.flags |= CC_NEGATED;
74  return \"andh %H1,%0,%?r0\";
75}")
76
77(define_insn ""
78  [(set (cc0) (eq (ashiftrt:SI
79		   (sign_extend:SI
80		    (ashift:QI (match_operand:QI 0 "register_operand" "r")
81			       (match_operand:QI 1 "logic_int" "n")))
82		   (match_operand:SI 2 "logic_int" "n"))
83		  (const_int 0)))]
84  ""
85  "*
86{
87  int width = 8 - INTVAL (operands[2]);
88  int pos = 8 - width - INTVAL (operands[1]);
89
90  CC_STATUS_PARTIAL_INIT;
91  operands[2] = GEN_INT (~((-1) << width) << pos);
92  return \"and %2,%0,%?r0\";
93}")
94
95;; -------------------------------------------------------------------------
96;; SImode signed integer comparisons
97;; -------------------------------------------------------------------------
98
99(define_insn "cmpeqsi"
100  [(set (cc0) (eq (match_operand:SI 0 "logic_operand" "r,rL")
101		  (match_operand:SI 1 "logic_operand" "L,r")))]
102  ""
103  "*
104{
105  CC_STATUS_PARTIAL_INIT;
106  if (REG_P (operands[0]))
107    return \"xor %1,%0,%?r0\";
108  else
109    return \"xor %0,%1,%?r0\";
110}")
111
112(define_insn "cmpnesi"
113  [(set (cc0) (ne (match_operand:SI 0 "logic_operand" "r,rL")
114		  (match_operand:SI 1 "logic_operand" "L,r")))]
115  ""
116  "*
117{
118  CC_STATUS_PARTIAL_INIT;
119  cc_status.flags |= CC_NEGATED;
120  if (REG_P (operands[0]))
121    return \"xor %1,%0,%?r0\";
122  else
123    return \"xor %0,%1,%?r0\";
124}")
125
126(define_insn "cmpltsi"
127  [(set (cc0) (lt (match_operand:SI 0 "arith_operand" "r,rI")
128		  (match_operand:SI 1 "arith_operand" "I,r")))]
129  ""
130  "*
131{
132  CC_STATUS_PARTIAL_INIT;
133  if (REG_P (operands[1]))
134    return \"subs %0,%1,%?r0\";
135  else
136    {
137      cc_status.flags |= CC_REVERSED;
138      operands[1] = GEN_INT (- INTVAL (operands[1]));
139      return \"adds %1,%0,%?r0\";
140    }
141}")
142
143(define_insn "cmpgtsi"
144  [(set (cc0) (gt (match_operand:SI 0 "arith_operand" "r,rI")
145		  (match_operand:SI 1 "arith_operand" "I,r")))]
146  ""
147  "*
148{
149  CC_STATUS_PARTIAL_INIT;
150  if (REG_P (operands[0]))
151    return \"subs %1,%0,%?r0\";
152  else
153    {
154      cc_status.flags |= CC_REVERSED;
155      operands[0] = GEN_INT (- INTVAL (operands[0]));
156      return \"adds %0,%1,%?r0\";
157    }
158}")
159
160(define_insn "cmplesi"
161  [(set (cc0) (le (match_operand:SI 0 "arith_operand" "r,rI")
162		  (match_operand:SI 1 "arith_operand" "I,r")))]
163  ""
164  "*
165{
166  CC_STATUS_PARTIAL_INIT;
167  cc_status.flags |= CC_NEGATED;
168  if (REG_P (operands[0]))
169    return \"subs %1,%0,%?r0\";
170  else
171    {
172      cc_status.flags |= CC_REVERSED;
173      operands[0] = GEN_INT (- INTVAL (operands[0]));
174      return \"adds %0,%1,%?r0\";
175    }
176}")
177
178(define_insn "cmpgesi"
179  [(set (cc0) (ge (match_operand:SI 0 "arith_operand" "r,rI")
180		  (match_operand:SI 1 "arith_operand" "I,r")))]
181  ""
182  "*
183{
184  CC_STATUS_PARTIAL_INIT;
185  cc_status.flags |= CC_NEGATED;
186  if (REG_P (operands[1]))
187    return \"subs %0,%1,%?r0\";
188  else
189    {
190      cc_status.flags |= CC_REVERSED;
191      operands[1] = GEN_INT (- INTVAL (operands[1]));
192      return \"adds %1,%0,%?r0\";
193    }
194}")
195
196;; -------------------------------------------------------------------------
197;; SImode unsigned integer comparisons
198;; -------------------------------------------------------------------------
199
200;; WARNING!  There is a small i860 hardware limitation (bug?) which we
201;; may run up against (if we are not careful) when we are trying to do
202;; unsigned comparisons like (x >= 0), (x < 0), (0 <= x), and (0 > x).
203;; Specifically, we must avoid using an `addu' instruction to perform
204;; such comparisons because the result (in the CC bit register) will
205;; come out wrong.  (This fact is documented in a footnote on page 7-10
206;; of the 1991 version of the i860 Microprocessor Family Programmer's
207;; Reference Manual).  Note that unsigned comparisons of this sort are
208;; always redundant anyway, because an unsigned quantity can never be
209;; less than zero.  When we see cases like this, we generate an
210;; `or K,%r0,%r0' instruction instead (where K is a constant 0 or -1)
211;; so as to get the CC bit register set properly for any subsequent
212;; conditional jump instruction.
213
214(define_insn "cmpgeusi"
215  [(set (cc0) (geu (match_operand:SI 0 "arith_operand" "r,rI")
216		   (match_operand:SI 1 "arith_operand" "I,r")))]
217  ""
218  "*
219{
220  CC_STATUS_PARTIAL_INIT;
221  if (REG_P (operands[1]))
222    return \"subu %0,%1,%?r0\";
223  else
224    {
225      if (INTVAL (operands[1]) == 0)
226	return \"or 0,%?r0,%?r0\";
227      else
228	{
229	  cc_status.flags |= CC_REVERSED;
230	  operands[1] = GEN_INT (- INTVAL (operands[1]));
231	  return \"addu %1,%0,%?r0\";
232	}
233    }
234}")
235
236(define_insn "cmpleusi"
237  [(set (cc0) (leu (match_operand:SI 0 "arith_operand" "r,rI")
238		   (match_operand:SI 1 "arith_operand" "I,r")))]
239  ""
240  "*
241{
242  CC_STATUS_PARTIAL_INIT;
243  if (REG_P (operands[0]))
244    return \"subu %1,%0,%?r0\";
245  else
246    {
247      if (INTVAL (operands[0]) == 0)
248	return \"or 0,%?r0,%?r0\";
249      else
250	{
251	  cc_status.flags |= CC_REVERSED;
252	  operands[0] = GEN_INT (- INTVAL (operands[0]));
253	  return \"addu %0,%1,%?r0\";
254	}
255    }
256}")
257
258;; -------------------------------------------------------------------------
259;; SFmode floating-point comparisons
260;; -------------------------------------------------------------------------
261
262(define_insn "cmpeqsf"
263  [(set (cc0) (eq (match_operand:SF 0 "reg_or_0_operand" "fG")
264		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
265  ""
266  "*
267{
268  CC_STATUS_PARTIAL_INIT;
269  return \"pfeq.ss %r0,%r1,%?f0\";
270}")
271
272(define_insn "cmpnesf"
273  [(set (cc0) (ne (match_operand:SF 0 "reg_or_0_operand" "fG")
274		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
275  ""
276  "*
277{
278  CC_STATUS_PARTIAL_INIT;
279  cc_status.flags |= CC_NEGATED;
280  return \"pfeq.ss %r1,%r0,%?f0\";
281}")
282
283;; NOTE:  The i860 Programmer's Reference Manual says that when we are
284;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these
285;; in order to be IEEE compliant (in case a trap occurs during these
286;; operations).  Conversely, for (A <= B) or (A >= B) comparisons, we
287;; must use pfle to be IEEE compliant.
288
289(define_insn "cmpltsf"
290  [(set (cc0) (lt (match_operand:SF 0 "reg_or_0_operand" "fG")
291		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
292  ""
293  "*
294{
295  CC_STATUS_PARTIAL_INIT;
296  return \"pfgt.ss %r1,%r0,%?f0\";
297}")
298
299(define_insn "cmpgtsf"
300  [(set (cc0) (gt (match_operand:SF 0 "reg_or_0_operand" "fG")
301		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
302  ""
303  "*
304{
305  CC_STATUS_PARTIAL_INIT;
306  return \"pfgt.ss %r0,%r1,%?f0\";
307}")
308
309;; NOTE:  The pfle opcode doesn't do what you think it does.  It is
310;; bass-ackwards.  It *clears* the CC flag if the first operand is
311;; less than or equal to the second.  Thus, we have to set CC_NEGATED
312;; for the following two patterns.
313
314(define_insn "cmplesf"
315  [(set (cc0) (le (match_operand:SF 0 "reg_or_0_operand" "fG")
316		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
317  ""
318  "*
319{
320  CC_STATUS_PARTIAL_INIT;
321  cc_status.flags |= CC_NEGATED;
322  return \"pfle.ss %r0,%r1,%?f0\";
323}")
324
325(define_insn "cmpgesf"
326  [(set (cc0) (ge (match_operand:SF 0 "reg_or_0_operand" "fG")
327		  (match_operand:SF 1 "reg_or_0_operand" "fG")))]
328  ""
329  "*
330{
331  CC_STATUS_PARTIAL_INIT;
332  cc_status.flags |= CC_NEGATED;
333  return \"pfle.ss %r1,%r0,%?f0\";
334}")
335
336;; -------------------------------------------------------------------------
337;; DFmode floating-point comparisons
338;; -------------------------------------------------------------------------
339
340(define_insn "cmpeqdf"
341  [(set (cc0) (eq (match_operand:DF 0 "reg_or_0_operand" "fG")
342		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
343  ""
344  "*
345{
346  CC_STATUS_PARTIAL_INIT;
347  return \"pfeq.dd %r0,%r1,%?f0\";
348}")
349
350(define_insn "cmpnedf"
351  [(set (cc0) (ne (match_operand:DF 0 "reg_or_0_operand" "fG")
352		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
353  ""
354  "*
355{
356  CC_STATUS_PARTIAL_INIT;
357  cc_status.flags |= CC_NEGATED;
358  return \"pfeq.dd %r1,%r0,%?f0\";
359}")
360
361;; NOTE:  The i860 Programmer's Reference Manual says that when we are
362;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these
363;; in order to be IEEE compliant (in case a trap occurs during these
364;; operations).  Conversely, for (A <= B) or (A >= B) comparisons, we
365;; must use pfle to be IEEE compliant.
366
367(define_insn "cmpltdf"
368  [(set (cc0) (lt (match_operand:DF 0 "reg_or_0_operand" "fG")
369		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
370  ""
371  "*
372{
373  CC_STATUS_PARTIAL_INIT;
374  return \"pfgt.dd %r1,%r0,%?f0\";
375}")
376
377(define_insn "cmpgtdf"
378  [(set (cc0) (gt (match_operand:DF 0 "reg_or_0_operand" "fG")
379		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
380  ""
381  "*
382{
383  CC_STATUS_PARTIAL_INIT;
384  return \"pfgt.dd %r0,%r1,%?f0\";
385}")
386
387;; NOTE:  The pfle opcode doesn't do what you think it does.  It is
388;; bass-ackwards.  It *clears* the CC flag if the first operand is
389;; less than or equal to the second.  Thus, we have to set CC_NEGATED
390;; for the following two patterns.
391
392(define_insn "cmpledf"
393  [(set (cc0) (le (match_operand:DF 0 "reg_or_0_operand" "fG")
394		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
395  ""
396  "*
397{
398  CC_STATUS_PARTIAL_INIT;
399  cc_status.flags |= CC_NEGATED;
400  return \"pfle.dd %r0,%r1,%?f0\";
401}")
402
403(define_insn "cmpgedf"
404  [(set (cc0) (ge (match_operand:DF 0 "reg_or_0_operand" "fG")
405		  (match_operand:DF 1 "reg_or_0_operand" "fG")))]
406  ""
407  "*
408{
409  CC_STATUS_PARTIAL_INIT;
410  cc_status.flags |= CC_NEGATED;
411  return \"pfle.dd %r1,%r0,%?f0\";
412}")
413
414;; ------------------------------------------------------------------------
415;; Integer EQ/NE comparisons against constant values which will fit in the
416;; 16-bit immediate field of an instruction.  These are made by combining.
417;; ------------------------------------------------------------------------
418
419(define_insn ""
420  [(set (cc0) (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m"))
421	          (match_operand:SI 1 "small_int" "I")))]
422  "INTVAL (operands[1]) >= 0"
423  "*
424{
425  CC_STATUS_PARTIAL_INIT;
426  return \"ld.s %0,%?r31\;xor %1,%?r31,%?r0\";
427}")
428
429(define_insn ""
430  [(set (cc0) (eq (match_operand:SI 0 "small_int" "I")
431	          (zero_extend:SI (match_operand:HI 1 "load_operand" "m"))))]
432  "INTVAL (operands[0]) >= 0"
433  "*
434{
435  CC_STATUS_PARTIAL_INIT;
436  return \"ld.s %1,%?r31\;xor %0,%?r31,%?r0\";
437}")
438
439;; ------------------------------------------------------------------------
440;; Define the real conditional branch instructions.
441;; ------------------------------------------------------------------------
442
443(define_insn "cbranch"
444  [(set (pc) (if_then_else (eq (cc0) (const_int 0))
445			   (label_ref (match_operand 0 "" ""))
446			   (pc)))]
447  ""
448  "*
449{
450  if ((cc_prev_status.flags & CC_NEGATED) == 0)
451    return \"bnc %l0\";
452  else
453    return \"bc %l0\";
454}")
455
456(define_insn "flipped_cbranch"
457  [(set (pc) (if_then_else (ne (cc0)
458			       (const_int 0))
459			   (pc)
460			   (label_ref (match_operand 0 "" ""))))]
461  ""
462  "*
463{
464  if ((cc_prev_status.flags & CC_NEGATED) == 0)
465    return \"bnc %l0\";
466  else
467    return \"bc %l0\";
468}")
469
470(define_insn "inverse_cbranch"
471  [(set (pc) (if_then_else (eq (cc0)
472			       (const_int 0))
473			   (pc)
474			   (label_ref (match_operand 0 "" ""))))]
475  ""
476  "*
477{
478  if ((cc_prev_status.flags & CC_NEGATED) == 0)
479    return \"bc %l0\";
480  else
481    return \"bnc %l0\";
482}")
483
484
485(define_insn "flipped_inverse_cbranch"
486  [(set (pc) (if_then_else (ne (cc0)
487			       (const_int 0))
488			   (label_ref (match_operand 0 "" ""))
489			   (pc)))]
490  ""
491  "*
492{
493  if ((cc_prev_status.flags & CC_NEGATED) == 0)
494    return \"bc %l0\";
495  else
496    return \"bnc %l0\";
497}")
498
499;; Simple BTE/BTNE compare-and-branch insns made by combining.
500;; Note that it is wrong to add similar patterns for QI or HImode
501;; because bte/btne always compare the whole register.
502
503(define_insn ""
504  [(set (pc)
505        (if_then_else (eq (match_operand:SI 0 "register_operand" "r")
506			  (match_operand:SI 1 "bte_operand" "rK"))
507		      (label_ref (match_operand 2 "" ""))
508		      (pc)))]
509  ""
510  "bte %1,%0,%2")
511
512(define_insn ""
513  [(set (pc)
514        (if_then_else (ne (match_operand:SI 0 "register_operand" "r")
515			  (match_operand:SI 1 "bte_operand" "rK"))
516		      (label_ref (match_operand 2 "" ""))
517		      (pc)))]
518  ""
519  "btne %1,%0,%2")
520
521(define_insn ""
522  [(set (pc)
523        (if_then_else (eq (match_operand:SI 0 "register_operand" "r")
524			  (match_operand:SI 1 "bte_operand" "rK"))
525		      (pc)
526		      (label_ref (match_operand 2 "" ""))))]
527  ""
528  "btne %1,%0,%2")
529
530(define_insn ""
531  [(set (pc)
532        (if_then_else (ne (match_operand:SI 0 "register_operand" "r")
533			  (match_operand:SI 1 "bte_operand" "rK"))
534		      (pc)
535		      (label_ref (match_operand 2 "" ""))))]
536  ""
537  "bte %1,%0,%2")
538
539;; Load byte/halfword, zero-extend, & compare-and-branch insns.
540;; These are made by combining.
541
542(define_insn ""
543  [(set (pc)
544        (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
545                          (match_operand:SI 1 "bte_operand" "K"))
546                      (label_ref (match_operand 2 "" ""))
547                      (pc)))
548   (match_scratch:SI 3 "=r")]
549  ""
550  "ld.b %0,%3;bte %1,%3,%2")
551
552(define_insn ""
553  [(set (pc)
554        (if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
555                          (match_operand:SI 1 "bte_operand" "K"))
556                      (label_ref (match_operand 2 "" ""))
557                      (pc)))
558   (match_scratch:SI 3 "=r")]
559  ""
560  "ld.b %0,%3;btne %1,%3,%2")
561
562(define_insn ""
563  [(set (pc)
564        (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
565                          (match_operand:SI 1 "bte_operand" "K"))
566                      (pc)
567                      (label_ref (match_operand 2 "" ""))))
568   (match_scratch:SI 3 "=r")]
569  ""
570  "ld.b %0,%3;btne %1,%3,%2")
571
572(define_insn ""
573  [(set (pc)
574        (if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
575                          (match_operand:SI 1 "bte_operand" "K"))
576                      (pc)
577                      (label_ref (match_operand 2 "" ""))))
578   (match_scratch:SI 3 "=r")]
579  ""
580  "ld.b %0,%3;bte %1,%3,%2")
581
582(define_insn ""
583  [(set (pc)
584        (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
585                          (match_operand:SI 1 "bte_operand" "K"))
586                      (label_ref (match_operand 2 "" ""))
587                      (pc)))
588   (match_scratch:SI 3 "=r")]
589  ""
590  "ld.s %0,%3;bte %1,%3,%2")
591
592(define_insn ""
593  [(set (pc)
594        (if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
595                          (match_operand:SI 1 "bte_operand" "K"))
596                      (label_ref (match_operand 2 "" ""))
597                      (pc)))
598   (match_scratch:SI 3 "=r")]
599  ""
600  "ld.s %0,%3;btne %1,%3,%2")
601
602(define_insn ""
603  [(set (pc)
604        (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
605                          (match_operand:SI 1 "bte_operand" "K"))
606                      (pc)
607                      (label_ref (match_operand 2 "" ""))))
608   (match_scratch:SI 3 "=r")]
609  ""
610  "ld.s %0,%3;btne %1,%3,%2")
611
612(define_insn ""
613  [(set (pc)
614        (if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
615                          (match_operand:SI 1 "bte_operand" "K"))
616                      (pc)
617                      (label_ref (match_operand 2 "" ""))))
618   (match_scratch:SI 3 "=r")]
619  ""
620  "ld.s %0,%3;bte %1,%3,%2")
621
622
623;; Generation of conditionals.
624
625;; We save the compare operands in the cmpxx patterns and use then when
626;; we generate the branch.
627
628(define_expand "cmpsi"
629  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
630		       (match_operand:SI 1 "compare_operand" "")))]
631  ""
632  "
633{ i860_compare_op0 = operands[0];
634  i860_compare_op1 = operands[1];
635  DONE;
636}")
637
638(define_expand "cmpsf"
639  [(set (cc0) (compare (match_operand:SF 0 "register_operand" "")
640		       (match_operand:SF 1 "register_operand" "")))]
641  ""
642  "
643{ i860_compare_op0 = operands[0];
644  i860_compare_op1 = operands[1];
645  DONE;
646}")
647
648(define_expand "cmpdf"
649  [(set (cc0) (compare (match_operand:DF 0 "register_operand" "")
650		       (match_operand:DF 1 "register_operand" "")))]
651  ""
652  "
653{ i860_compare_op0 = operands[0];
654  i860_compare_op1 = operands[1];
655  DONE;
656}")
657
658;; These are the standard-named conditional branch patterns.
659;; Detailed comments are found in the first one only.
660
661(define_expand "beq"
662  [(set (pc)
663	(if_then_else (eq (cc0)
664			  (const_int 0))
665		      (label_ref (match_operand 0 "" ""))
666		      (pc)))]
667  ""
668  "
669{
670  /* Emit a single-condition compare insn according to
671     the type of operands and the condition to be tested.  */
672
673  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
674    emit_insn (gen_cmpeqsi (i860_compare_op0, i860_compare_op1));
675  else if (GET_MODE (i860_compare_op0) == SFmode)
676    emit_insn (gen_cmpeqsf (i860_compare_op0, i860_compare_op1));
677  else if (GET_MODE (i860_compare_op0) == DFmode)
678    emit_insn (gen_cmpeqdf (i860_compare_op0, i860_compare_op1));
679  else
680    abort ();
681
682  /* Emit branch-if-true.  */
683
684  emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
685  DONE;
686}")
687
688(define_expand "bne"
689  [(set (pc)
690	(if_then_else (ne (cc0)
691			  (const_int 0))
692		      (label_ref (match_operand 0 "" ""))
693		      (pc)))]
694  ""
695  "
696{
697  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
698    emit_insn (gen_cmpeqsi (i860_compare_op0, i860_compare_op1));
699  else if (GET_MODE (i860_compare_op0) == SFmode)
700    emit_insn (gen_cmpeqsf (i860_compare_op0, i860_compare_op1));
701  else if (GET_MODE (i860_compare_op0) == DFmode)
702    emit_insn (gen_cmpeqdf (i860_compare_op0, i860_compare_op1));
703  else
704    abort ();
705
706  emit_jump_insn (gen_flipped_cbranch (operands[0]));
707
708  DONE;
709}")
710
711(define_expand "bgt"
712  [(set (pc)
713	(if_then_else (gt (cc0)
714			  (const_int 0))
715		      (label_ref (match_operand 0 "" ""))
716		      (pc)))]
717  ""
718  "
719{
720  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
721    emit_insn (gen_cmpgtsi (i860_compare_op0, i860_compare_op1));
722  else if (GET_MODE (i860_compare_op0) == SFmode)
723    emit_insn (gen_cmpgtsf (i860_compare_op0, i860_compare_op1));
724  else if (GET_MODE (i860_compare_op0) == DFmode)
725    emit_insn (gen_cmpgtdf (i860_compare_op0, i860_compare_op1));
726  else
727    abort ();
728
729  emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
730  DONE;
731}")
732
733(define_expand "blt"
734  [(set (pc)
735	(if_then_else (lt (cc0)
736			  (const_int 0))
737		      (label_ref (match_operand 0 "" ""))
738		      (pc)))]
739  ""
740  "
741{
742  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
743    emit_insn (gen_cmpltsi (i860_compare_op0, i860_compare_op1));
744  else if (GET_MODE (i860_compare_op0) == SFmode)
745    emit_insn (gen_cmpltsf (i860_compare_op0, i860_compare_op1));
746  else if (GET_MODE (i860_compare_op0) == DFmode)
747    emit_insn (gen_cmpltdf (i860_compare_op0, i860_compare_op1));
748  else
749    abort ();
750
751  emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
752  DONE;
753}")
754
755(define_expand "ble"
756  [(set (pc)
757	(if_then_else (le (cc0)
758			  (const_int 0))
759		      (label_ref (match_operand 0 "" ""))
760		      (pc)))]
761  ""
762  "
763{
764  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
765    {
766      emit_insn (gen_cmpgtsi (i860_compare_op0, i860_compare_op1));
767      emit_jump_insn (gen_flipped_cbranch (operands[0]));
768    }
769  else
770    {
771      if (GET_MODE (i860_compare_op0) == SFmode)
772	emit_insn (gen_cmplesf (i860_compare_op0, i860_compare_op1));
773      else if (GET_MODE (i860_compare_op0) == DFmode)
774	emit_insn (gen_cmpledf (i860_compare_op0, i860_compare_op1));
775      else
776	abort ();
777      emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
778    }
779  DONE;
780}")
781
782(define_expand "bge"
783  [(set (pc)
784	(if_then_else (ge (cc0)
785			  (const_int 0))
786		      (label_ref (match_operand 0 "" ""))
787		      (pc)))]
788  ""
789  "
790{
791  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) == MODE_INT)
792    {
793      emit_insn (gen_cmpltsi (i860_compare_op0, i860_compare_op1));
794      emit_jump_insn (gen_flipped_cbranch (operands[0]));
795    }
796  else
797    {
798      if (GET_MODE (i860_compare_op0) == SFmode)
799	emit_insn (gen_cmpgesf (i860_compare_op0, i860_compare_op1));
800      else if (GET_MODE (i860_compare_op0) == DFmode)
801	emit_insn (gen_cmpgedf (i860_compare_op0, i860_compare_op1));
802      else
803	abort ();
804      emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
805    }
806  DONE;
807}")
808
809(define_expand "bgtu"
810  [(set (pc)
811	(if_then_else (gtu (cc0)
812			   (const_int 0))
813		      (label_ref (match_operand 0 "" ""))
814		      (pc)))]
815  ""
816  "
817{
818  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT)
819    abort ();
820
821  emit_insn (gen_cmpleusi (i860_compare_op0, i860_compare_op1));
822  emit_jump_insn (gen_flipped_cbranch (operands[0]));
823  DONE;
824}")
825
826(define_expand "bltu"
827  [(set (pc)
828	(if_then_else (ltu (cc0)
829			   (const_int 0))
830		      (label_ref (match_operand 0 "" ""))
831		      (pc)))]
832  ""
833  "
834{
835  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT)
836    abort ();
837
838  emit_insn (gen_cmpgeusi (i860_compare_op0, i860_compare_op1));
839  emit_jump_insn (gen_flipped_cbranch (operands[0]));
840  DONE;
841}")
842
843(define_expand "bgeu"
844  [(set (pc)
845	(if_then_else (geu (cc0)
846			   (const_int 0))
847		      (label_ref (match_operand 0 "" ""))
848		      (pc)))]
849  ""
850  "
851{
852  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT)
853    abort ();
854
855  emit_insn (gen_cmpgeusi (i860_compare_op0, i860_compare_op1));
856  emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
857  DONE;
858}")
859
860(define_expand "bleu"
861  [(set (pc)
862	(if_then_else (leu (cc0)
863			   (const_int 0))
864		      (label_ref (match_operand 0 "" ""))
865		      (pc)))]
866  ""
867  "
868{
869  if (GET_MODE_CLASS (GET_MODE (i860_compare_op0)) != MODE_INT)
870    abort ();
871
872  emit_insn (gen_cmpleusi (i860_compare_op0, i860_compare_op1));
873  emit_jump_insn (gen_flipped_inverse_cbranch (operands[0]));
874  DONE;
875}")
876
877;; Move instructions
878
879;; Note that source operands for `mov' pseudo-instructions are no longer
880;; allowed (by the svr4 assembler) to be "big" things, i.e. constants that
881;; won't fit in 16-bits.  (This includes any sort of a relocatable address
882;; also.)  Thus, we must use an explicit orh/or pair of instructions if
883;; the source operand is something "big".
884
885(define_insn "movsi"
886  [(set (match_operand:SI 0 "general_operand" "=r,m,f")
887	(match_operand:SI 1 "general_operand" "rmif,rfJ,rmfJ"))]
888  ""
889  "*
890{
891  if (GET_CODE (operands[0]) == MEM)
892    {
893      if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
894	return output_store (operands);
895      if (FP_REG_P (operands[1]))
896	return \"fst.l %1,%0\";
897      return \"st.l %r1,%0\";
898    }
899  if (GET_CODE (operands[1]) == MEM)
900    {
901      if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
902	return output_load (operands);
903      if (FP_REG_P (operands[0]))
904	return \"fld.l %1,%0\";
905      return \"ld.l %1,%0\";
906    }
907  if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
908    return \"fmov.ss %1,%0\";
909  if (FP_REG_P (operands[1]))
910    return \"fxfr %1,%0\";
911  if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
912    return \"fmov.ss %?f0,%0\";
913  if (FP_REG_P (operands[0]))
914    return \"ixfr %1,%0\";
915
916  if (GET_CODE (operands[1]) == REG)
917    return \"shl %?r0,%1,%0\";
918
919  CC_STATUS_PARTIAL_INIT;
920
921  if (GET_CODE (operands[1]) == CONST_INT)
922    {
923      if((INTVAL (operands[1]) & 0xffff0000) == 0)
924        return \"or %L1,%?r0,%0\";
925      if((INTVAL (operands[1]) & 0x0000ffff) == 0)
926        return \"orh %H1,%?r0,%0\";
927    }
928  return \"orh %H1,%?r0,%0\;or %L1,%0,%0\";
929}")
930 
931(define_insn "movhi"
932  [(set (match_operand:HI 0 "general_operand" "=r,m,!*f,!r")
933	(match_operand:HI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
934  ""
935  "*
936{
937  if (GET_CODE (operands[0]) == MEM)
938    {
939      if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
940	return output_store (operands);
941      return \"st.s %r1,%0\";
942    }
943  if (GET_CODE (operands[1]) == MEM)
944    {
945      if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
946	return output_load (operands);
947      return \"ld.s %1,%0\";
948    }
949  if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
950    return \"fmov.ss %1,%0\";
951  if (FP_REG_P (operands[1]))
952    return \"fxfr %1,%0\";
953  if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
954    return \"fmov.ss %?f0,%0\";
955  if (FP_REG_P (operands[0]))
956    return \"ixfr %1,%0\";
957
958  if (GET_CODE (operands[1]) == REG)
959    return \"shl %?r0,%1,%0\";
960
961  CC_STATUS_PARTIAL_INIT;
962
963  return \"or %L1,%?r0,%0\";
964}")
965
966(define_insn "movqi"
967  [(set (match_operand:QI 0 "general_operand" "=r,m,!*f,!r")
968	(match_operand:QI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
969  ""
970  "*
971{
972  if (GET_CODE (operands[0]) == MEM)
973    {
974      if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
975	return output_store (operands);
976      return \"st.b %r1,%0\";
977    }
978  if (GET_CODE (operands[1]) == MEM)
979    {
980      if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
981	return output_load (operands);
982      return \"ld.b %1,%0\";
983    }
984  if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
985    return \"fmov.ss %1,%0\";
986  if (FP_REG_P (operands[1]))
987    return \"fxfr %1,%0\";
988  if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
989    return \"fmov.ss %?f0,%0\";
990  if (FP_REG_P (operands[0]))
991    return \"ixfr %1,%0\";
992
993  if (GET_CODE (operands[1]) == REG)
994    return \"shl %?r0,%1,%0\";
995
996  CC_STATUS_PARTIAL_INIT;
997
998  return \"or %L1,%?r0,%0\";
999}")
1000
1001;; The definition of this insn does not really explain what it does,
1002;; but it should suffice
1003;; that anything generated as this insn will be recognized as one
1004;; and that it won't successfully combine with anything.
1005(define_expand "movstrsi"
1006  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
1007		   (match_operand:BLK 1 "general_operand" ""))
1008	      (use (match_operand:SI 2 "nonmemory_operand" ""))
1009	      (use (match_operand:SI 3 "immediate_operand" ""))
1010	      (clobber (match_dup 4))
1011	      (clobber (match_dup 5))
1012	      (clobber (match_dup 6))
1013	      (clobber (match_dup 7))
1014	      (clobber (match_dup 8))])]
1015  ""
1016  "
1017{
1018  operands[4] = gen_reg_rtx (SImode);
1019  operands[5] = gen_reg_rtx (SImode);
1020  operands[6] = gen_reg_rtx (SImode);
1021  operands[7] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
1022  operands[8] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
1023
1024  operands[0] = change_address (operands[0], VOIDmode, operands[7]);
1025  operands[1] = change_address (operands[1], VOIDmode, operands[8]);
1026}")
1027
1028(define_insn ""
1029  [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
1030	(mem:BLK (match_operand:SI 1 "register_operand" "r")))
1031   (use (match_operand:SI 2 "general_operand" "rn"))
1032   (use (match_operand:SI 3 "immediate_operand" "i"))
1033   (clobber (match_operand:SI 4 "register_operand" "=r"))
1034   (clobber (match_operand:SI 5 "register_operand" "=r"))
1035   (clobber (match_operand:SI 6 "register_operand" "=r"))
1036   (clobber (match_dup 0))
1037   (clobber (match_dup 1))]
1038  ""
1039  "* return output_block_move (operands);")
1040
1041;; Floating point move insns
1042
1043;; This pattern forces (set (reg:DF ...) (const_double ...))
1044;; to be reloaded by putting the constant into memory.
1045;; It must come before the more general movdf pattern.
1046(define_insn ""
1047  [(set (match_operand:DF 0 "general_operand" "=r,f,o")
1048	(match_operand:DF 1 "" "mG,m,G"))]
1049  "GET_CODE (operands[1]) == CONST_DOUBLE"
1050  "*
1051{
1052  if (FP_REG_P (operands[0]) || operands[1] == CONST0_RTX (DFmode))
1053    return output_fp_move_double (operands);
1054  return output_move_double (operands);
1055}")
1056
1057(define_insn "movdf"
1058  [(set (match_operand:DF 0 "general_operand" "=*rm,*r,?f,?*rm")
1059	(match_operand:DF 1 "general_operand" "*r,m,*rfmG,f"))]
1060  ""
1061  "*
1062{
1063  if (GET_CODE (operands[0]) == MEM
1064      && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1065    return output_store (operands);
1066  if (GET_CODE (operands[1]) == MEM
1067      && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1068    return output_load (operands);
1069
1070  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1071    return output_fp_move_double (operands);
1072  return output_move_double (operands);
1073}")
1074
1075(define_insn "movdi"
1076  [(set (match_operand:DI 0 "general_operand" "=rm,r,?f,?rm")
1077	(match_operand:DI 1 "general_operand" "r,miF,rfmG,f"))]
1078  ""
1079  "*
1080{
1081  if (GET_CODE (operands[0]) == MEM
1082      && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1083    return output_store (operands);
1084  if (GET_CODE (operands[1]) == MEM
1085      && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1086    return output_load (operands);
1087
1088  /* ??? How can we have a DFmode arg here with DImode above? */
1089  if (FP_REG_P (operands[0]) && operands[1] == CONST0_RTX (DFmode))
1090    return \"fmov.dd %?f0,%0\";
1091
1092  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
1093    return output_fp_move_double (operands);
1094  return output_move_double (operands);
1095}")
1096
1097;; The alternative m/r is separate from m/f
1098;; The first alternative is separate from the second for the same reason.
1099(define_insn "movsf"
1100  [(set (match_operand:SF 0 "general_operand" "=*rf,*rf,*r,m,m")
1101	(match_operand:SF 1 "general_operand" "*r,fmG,F,*r,f"))]
1102  ""
1103  "*
1104{
1105  if (GET_CODE (operands[0]) == MEM
1106      && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1107    return output_store (operands);
1108  if (GET_CODE (operands[1]) == MEM
1109      && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1110    return output_load (operands);
1111  if (FP_REG_P (operands[0]))
1112    {
1113      if (FP_REG_P (operands[1]))
1114	return \"fmov.ss %1,%0\";
1115      if (GET_CODE (operands[1]) == REG)
1116	return \"ixfr %1,%0\";
1117      if (operands[1] == CONST0_RTX (SFmode))
1118        return \"fmov.ss %?f0,%0\";
1119      if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1120	{
1121	  if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1122		 && (cc_prev_status.flags & CC_HI_R31_ADJ)
1123		 && cc_prev_status.mdep == XEXP(operands[1],0)))
1124	    {
1125	      CC_STATUS_INIT;
1126	      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1127	      cc_status.mdep = XEXP (operands[1], 0);
1128	      return \"orh %h1,%?r0,%?r31\;fld.l %L1(%?r31),%0\";
1129	    }
1130	  return \"fld.l %L1(%?r31),%0\";
1131	}
1132      return \"fld.l %1,%0\";
1133    }
1134  if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
1135    {
1136      if (GET_CODE (operands[0]) == REG && FP_REG_P (operands[1]))
1137	return \"fxfr %1,%0\";
1138      if (GET_CODE (operands[0]) == REG)
1139	{
1140	  CC_STATUS_PARTIAL_INIT;
1141	  if (GET_CODE (operands[1]) == CONST_DOUBLE)
1142	    {
1143	      register unsigned long ul;
1144
1145              ul = sfmode_constant_to_ulong (operands[1]);
1146	      if ((ul & 0x0000ffff) == 0)
1147		return \"orh %H1,%?r0,%0\";
1148	      if ((ul & 0xffff0000) == 0)
1149		return \"or %L1,%?r0,%0\";
1150	    }
1151          return \"orh %H1,%?r0,%0\;or %L1,%0,%0\";
1152	}
1153      /* Now operand 0 must be memory.
1154         If operand 1 is CONST_DOUBLE, its value must be 0.  */
1155      if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1156	{
1157	  if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1158		 && (cc_prev_status.flags & CC_HI_R31_ADJ)
1159		 && XEXP (operands[0], 0) == cc_prev_status.mdep))
1160	    {
1161	      CC_STATUS_INIT;
1162	      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1163	      cc_status.mdep = XEXP (operands[0], 0);
1164	      output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
1165	    }
1166	  return \"fst.l %r1,%L0(%?r31)\";
1167	}
1168      return \"fst.l %r1,%0\";
1169    }
1170  if (GET_CODE (operands[0]) == MEM)
1171    return \"st.l %r1,%0\";
1172  if (GET_CODE (operands[1]) == MEM)
1173    return \"ld.l %1,%0\";
1174  if (operands[1] == CONST0_RTX (SFmode))
1175    return \"shl %?r0,%?r0,%0\";
1176  return \"mov %1,%0\";
1177}")
1178
1179;; Special load insns for REG+REG addresses.
1180;; Such addresses are not "legitimate" because st rejects them.
1181
1182(define_insn ""
1183  [(set (match_operand:DF 0 "register_operand" "=rf")
1184	(match_operand:DF 1 "indexed_operand" "m"))]
1185  ""
1186  "*
1187{
1188  if (FP_REG_P (operands[0]))
1189    return output_fp_move_double (operands);
1190  return output_move_double (operands);
1191}")
1192
1193(define_insn ""
1194  [(set (match_operand:SF 0 "register_operand" "=rf")
1195	(match_operand:SF 1 "indexed_operand" "m"))]
1196  ""
1197  "*
1198{
1199  if (FP_REG_P (operands[0]))
1200    return \"fld.l %1,%0\";
1201  return \"ld.l %1,%0\";
1202}")
1203
1204(define_insn ""
1205  [(set (match_operand:SI 0 "register_operand" "=rf")
1206	(match_operand:SI 1 "indexed_operand" "m"))]
1207  ""
1208  "*
1209{
1210  if (FP_REG_P (operands[0]))
1211    return \"fld.l %1,%0\";
1212  return \"ld.l %1,%0\";
1213}")
1214
1215(define_insn ""
1216  [(set (match_operand:HI 0 "register_operand" "=r")
1217	(match_operand:HI 1 "indexed_operand" "m"))]
1218  ""
1219  "ld.s %1,%0")
1220
1221(define_insn ""
1222  [(set (match_operand:QI 0 "register_operand" "=r")
1223	(match_operand:QI 1 "indexed_operand" "m"))]
1224  ""
1225  "ld.b %1,%0")
1226
1227;; Likewise for floating-point store insns.
1228
1229(define_insn ""
1230  [(set (match_operand:DF 0 "indexed_operand" "=m")
1231	(match_operand:DF 1 "register_operand" "f"))]
1232  ""
1233  "fst.d %1,%0")
1234
1235(define_insn ""
1236  [(set (match_operand:SF 0 "indexed_operand" "=m")
1237	(match_operand:SF 1 "register_operand" "f"))]
1238  ""
1239  "fst.l %1,%0")
1240
1241;;- truncation instructions
1242(define_insn "truncsiqi2"
1243  [(set (match_operand:QI 0 "general_operand" "=g")
1244	(truncate:QI
1245	 (match_operand:SI 1 "register_operand" "r")))]
1246  ""
1247  "*
1248{
1249  if (GET_CODE (operands[0]) == MEM)
1250    if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1251      {
1252	if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1253	       && (cc_prev_status.flags & CC_HI_R31_ADJ)
1254	       && XEXP (operands[0], 0) == cc_prev_status.mdep))
1255	  {
1256	    CC_STATUS_INIT;
1257	    cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1258	    cc_status.mdep = XEXP (operands[0], 0);
1259	    output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
1260	  }
1261	return \"st.b %1,%L0(%?r31)\";
1262      }
1263    else
1264      return \"st.b %1,%0\";
1265  return \"shl %?r0,%1,%0\";
1266}")
1267
1268(define_insn "trunchiqi2"
1269  [(set (match_operand:QI 0 "general_operand" "=g")
1270	(truncate:QI
1271	 (match_operand:HI 1 "register_operand" "r")))]
1272  ""
1273  "*
1274{
1275  if (GET_CODE (operands[0]) == MEM)
1276    if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1277      {
1278	if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1279	       && (cc_prev_status.flags & CC_HI_R31_ADJ)
1280	       && XEXP (operands[0], 0) == cc_prev_status.mdep))
1281	  {
1282	    CC_STATUS_INIT;
1283	    cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1284	    cc_status.mdep = XEXP (operands[0], 0);
1285	    output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
1286	  }
1287	return \"st.b %1,%L0(%?r31)\";
1288      }
1289    else
1290      return \"st.b %1,%0\";
1291  return \"shl %?r0,%1,%0\";
1292}")
1293
1294(define_insn "truncsihi2"
1295  [(set (match_operand:HI 0 "general_operand" "=g")
1296	(truncate:HI
1297	 (match_operand:SI 1 "register_operand" "r")))]
1298  ""
1299  "*
1300{
1301  if (GET_CODE (operands[0]) == MEM)
1302    if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
1303      {
1304	if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1305	       && (cc_prev_status.flags & CC_HI_R31_ADJ)
1306	       && XEXP (operands[0], 0) == cc_prev_status.mdep))
1307	  {
1308	    CC_STATUS_INIT;
1309	    cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1310	    cc_status.mdep = XEXP (operands[0], 0);
1311	    output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
1312	  }
1313	return \"st.s %1,%L0(%?r31)\";
1314      }
1315    else
1316      return \"st.s %1,%0\";
1317  return \"shl %?r0,%1,%0\";
1318}")
1319
1320;;- zero extension instructions
1321
1322(define_insn "zero_extendhisi2"
1323  [(set (match_operand:SI 0 "register_operand" "=r")
1324	(zero_extend:SI
1325	 (match_operand:HI 1 "register_operand" "r")))]
1326  ""
1327  "*
1328{
1329  CC_STATUS_PARTIAL_INIT;
1330  return \"and 0xffff,%1,%0\";
1331}")
1332
1333(define_insn "zero_extendqihi2"
1334  [(set (match_operand:HI 0 "register_operand" "=r")
1335	(zero_extend:HI
1336	 (match_operand:QI 1 "register_operand" "r")))]
1337  ""
1338  "*
1339{
1340  CC_STATUS_PARTIAL_INIT;
1341  return \"and 0xff,%1,%0\";
1342}")
1343
1344(define_insn "zero_extendqisi2"
1345  [(set (match_operand:SI 0 "register_operand" "=r")
1346	(zero_extend:SI
1347	 (match_operand:QI 1 "register_operand" "r")))]
1348  ""
1349  "*
1350{
1351  CC_STATUS_PARTIAL_INIT;
1352  return \"and 0xff,%1,%0\";
1353}")
1354
1355;; Sign extension instructions.
1356
1357(define_insn ""
1358  [(set (match_operand:SI 0 "register_operand" "=r")
1359	(sign_extend:SI
1360	 (match_operand:HI 1 "indexed_operand" "m")))]
1361  ""
1362  "ld.s %1,%0")
1363
1364(define_insn ""
1365  [(set (match_operand:HI 0 "register_operand" "=r")
1366	(sign_extend:HI
1367	 (match_operand:QI 1 "indexed_operand" "m")))]
1368  ""
1369  "ld.b %1,%0")
1370
1371(define_insn ""
1372  [(set (match_operand:SI 0 "register_operand" "=r")
1373	(sign_extend:SI
1374	 (match_operand:QI 1 "indexed_operand" "m")))]
1375  ""
1376  "ld.b %1,%0")
1377
1378(define_insn "extendhisi2"
1379  [(set (match_operand:SI 0 "register_operand" "=r")
1380	(sign_extend:SI
1381	 (match_operand:HI 1 "nonimmediate_operand" "mr")))]
1382  ""
1383  "*
1384{
1385  if (REG_P (operands[1]))
1386    return \"shl 16,%1,%0\;shra 16,%0,%0\";
1387  if (GET_CODE (operands[1]) == CONST_INT)
1388    abort ();
1389  if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1390    {
1391      CC_STATUS_INIT;
1392      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1393      cc_status.mdep = XEXP (operands[1], 0);
1394      return \"orh %h1,%?r0,%?r31\;ld.s %L1(%?r31),%0\";
1395    }
1396  else
1397    return \"ld.s %1,%0\";
1398}")
1399
1400(define_insn "extendqihi2"
1401  [(set (match_operand:HI 0 "register_operand" "=r")
1402	(sign_extend:HI
1403	 (match_operand:QI 1 "nonimmediate_operand" "mr")))]
1404  ""
1405  "*
1406{
1407  if (REG_P (operands[1]))
1408    return \"shl 24,%1,%0\;shra 24,%0,%0\";
1409  if (GET_CODE (operands[1]) == CONST_INT)
1410    abort ();
1411  if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1412    {
1413      CC_STATUS_INIT;
1414      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1415      cc_status.mdep = XEXP (operands[1], 0);
1416      return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
1417    }
1418  else
1419    return \"ld.b %1,%0\";
1420}")
1421
1422(define_insn "extendqisi2"
1423  [(set (match_operand:SI 0 "register_operand" "=r")
1424	(sign_extend:SI
1425	 (match_operand:QI 1 "nonimmediate_operand" "mr")))]
1426  ""
1427  "*
1428{
1429  if (REG_P (operands[1]))
1430    return \"shl 24,%1,%0\;shra 24,%0,%0\";
1431  if (GET_CODE (operands[1]) == CONST_INT)
1432    abort ();
1433  if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
1434    {
1435      CC_STATUS_INIT;
1436      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1437      cc_status.mdep = XEXP (operands[1], 0);
1438      return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
1439    }
1440  else
1441    return \"ld.b %1,%0\";
1442}")
1443
1444;; Signed bitfield extractions come out looking like
1445;;	(shiftrt (sign_extend (shift <Y> <C1>)) <C2>)
1446;; which we expand poorly as four shift insns.
1447;; These patterns yield two shifts:
1448;;	(shiftrt (shift <Y> <C3>) <C4>)
1449(define_insn ""
1450  [(set (match_operand:SI 0 "register_operand" "=r")
1451	(ashiftrt:SI
1452	 (sign_extend:SI
1453	  (match_operand:QI 1 "register_operand" "r"))
1454	 (match_operand:SI 2 "logic_int" "n")))]
1455  "INTVAL (operands[2]) < 8"
1456  "*
1457{
1458  return \"shl 24,%1,%0\;shra 24+%2,%0,%0\";
1459}")
1460
1461(define_insn ""
1462  [(set (match_operand:SI 0 "register_operand" "=r")
1463	(ashiftrt:SI
1464	 (sign_extend:SI
1465	  (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r")
1466				(match_operand:SI 2 "logic_int" "n")) 0))
1467	 (match_operand:SI 3 "logic_int" "n")))]
1468  "INTVAL (operands[3]) < 8"
1469  "*
1470{
1471  return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
1472}")
1473
1474(define_insn ""
1475  [(set (match_operand:SI 0 "register_operand" "=r")
1476	(ashiftrt:SI
1477	 (sign_extend:SI
1478	  (ashift:QI (match_operand:QI 1 "register_operand" "r")
1479		     (match_operand:QI 2 "logic_int" "n")))
1480	 (match_operand:SI 3 "logic_int" "n")))]
1481  "INTVAL (operands[3]) < 8"
1482  "*
1483{
1484  return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
1485}")
1486
1487;; Special patterns for optimizing bit-field instructions.
1488
1489;; First two patterns are for bitfields that came from memory
1490;; testing only the high bit.  They work with old combiner.
1491
1492(define_insn ""
1493  [(set (cc0)
1494	(eq (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
1495						    (const_int 7)) 0))
1496	    (const_int 0)))]
1497  ""
1498  "*
1499{
1500  CC_STATUS_PARTIAL_INIT;
1501  return \"and 128,%0,%?r0\";
1502}")
1503
1504(define_insn ""
1505  [(set (cc0)
1506	(eq (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
1507						    (const_int 7)) 0))
1508	    (const_int 0)))]
1509  ""
1510  "*
1511{
1512  CC_STATUS_PARTIAL_INIT;
1513  return \"and 128,%0,%?r0\";
1514}")
1515
1516;; next two patterns are good for bitfields coming from memory
1517;; (via pseudo-register) or from a register, though this optimization
1518;; is only good for values contained wholly within the bottom 13 bits
1519(define_insn ""
1520  [(set (cc0)
1521	(eq 
1522	 (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
1523			      (match_operand:SI 1 "logic_int" "n"))
1524		 (match_operand:SI 2 "logic_int" "n"))
1525	 (const_int 0)))]
1526  "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
1527  "*
1528{
1529  CC_STATUS_PARTIAL_INIT;
1530  operands[2] = GEN_INT ((INTVAL (operands[2]) << INTVAL (operands[1])));
1531  return \"and %2,%0,%?r0\";
1532}")
1533
1534(define_insn ""
1535  [(set (cc0)
1536	(eq 
1537	 (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
1538			      (match_operand:SI 1 "logic_int" "n"))
1539		 (match_operand:SI 2 "logic_int" "n"))
1540	 (const_int 0)))]
1541  "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
1542  "*
1543{
1544  CC_STATUS_PARTIAL_INIT;
1545  operands[2] = GEN_INT ((INTVAL (operands[2]) << INTVAL (operands[1])));
1546  return \"and %2,%0,%?r0\";
1547}")
1548
1549;; Conversions between float and double.
1550
1551(define_insn "extendsfdf2"
1552  [(set (match_operand:DF 0 "register_operand" "=f")
1553	(float_extend:DF
1554	 (match_operand:SF 1 "register_operand" "f")))]
1555  ""
1556  "fmov.sd %1,%0")
1557
1558(define_insn "truncdfsf2"
1559  [(set (match_operand:SF 0 "register_operand" "=f")
1560	(float_truncate:SF
1561	 (match_operand:DF 1 "register_operand" "f")))]
1562  ""
1563  "fmov.ds %1,%0")
1564
1565;; Conversion between fixed point and floating point.
1566;; Note that among the fix-to-float insns
1567;; the ones that start with SImode come first.
1568;; That is so that an operand that is a CONST_INT
1569;; (and therefore lacks a specific machine mode).
1570;; will be recognized as SImode (which is always valid)
1571;; rather than as QImode or HImode.
1572
1573;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...)))
1574;; to be reloaded by putting the constant into memory.
1575;; It must come before the more general floatsisf2 pattern.
1576(define_expand "floatsidf2"
1577  [(set (match_dup 2) (match_dup 3))
1578   (set (match_dup 4) (xor:SI (match_operand:SI 1 "register_operand" "")
1579			      (const_int -2147483648)))
1580   (set (match_dup 5) (match_dup 3))
1581   (set (subreg:SI (match_dup 5) 0) (match_dup 4))
1582   (set (match_operand:DF 0 "register_operand" "")
1583	(minus:DF (match_dup 5) (match_dup 2)))]
1584  ""
1585  "
1586{
1587  REAL_VALUE_TYPE d;
1588  /* 4503601774854144 is  (1 << 30) * ((1 << 22) + (1 << 1)).  */
1589  d = REAL_VALUE_ATOF (\"4503601774854144\", DFmode);
1590  operands[2] = gen_reg_rtx (DFmode);
1591  operands[3] = CONST_DOUBLE_FROM_REAL_VALUE (d, DFmode);
1592  operands[4] = gen_reg_rtx (SImode);
1593  operands[5] = gen_reg_rtx (DFmode);
1594}")
1595
1596;; Floating to fixed conversion.
1597
1598(define_expand "fix_truncdfsi2"
1599  ;; This first insn produces a double-word value
1600  ;; in which only the low word is valid.
1601  [(set (match_dup 2)
1602	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
1603   (set (match_operand:SI 0 "register_operand" "=f")
1604	(subreg:SI (match_dup 2) 0))]
1605  ""
1606  "
1607{
1608  operands[2] = gen_reg_rtx (DImode);
1609}")
1610
1611;; Recognize the first insn generated above.
1612;; This RTL looks like a fix_truncdfdi2 insn,
1613;; but we dont call it that, because only 32 bits
1614;; of the result are valid.
1615;; This pattern will work for the intended purposes 
1616;; as long as we do not have any fixdfdi2 or fix_truncdfdi2.
1617(define_insn ""
1618  [(set (match_operand:DI 0 "register_operand" "=f")
1619	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
1620  ""
1621  "ftrunc.dd %1,%0")
1622
1623(define_expand "fix_truncsfsi2"
1624  ;; This first insn produces a double-word value
1625  ;; in which only the low word is valid.
1626  [(set (match_dup 2)
1627	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
1628   (set (match_operand:SI 0 "register_operand" "=f")
1629	(subreg:SI (match_dup 2) 0))]
1630  ""
1631  "
1632{
1633  operands[2] = gen_reg_rtx (DImode);
1634}")
1635
1636;; Recognize the first insn generated above.
1637;; This RTL looks like a fix_truncsfdi2 insn,
1638;; but we dont call it that, because only 32 bits
1639;; of the result are valid.
1640;; This pattern will work for the intended purposes 
1641;; as long as we do not have any fixsfdi2 or fix_truncsfdi2.
1642(define_insn ""
1643  [(set (match_operand:DI 0 "register_operand" "=f")
1644	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
1645  ""
1646  "ftrunc.sd %1,%0")
1647
1648;;- arithmetic instructions
1649
1650(define_insn "addsi3"
1651  [(set (match_operand:SI 0 "register_operand" "=r,*f")
1652	(plus:SI (match_operand:SI 1 "nonmemory_operand" "%r,*f")
1653		 (match_operand:SI 2 "arith_operand" "rI,*f")))]
1654  ""
1655  "*
1656{
1657  if (which_alternative == 1)
1658    return \"fiadd.ss %2,%1,%0\";
1659  CC_STATUS_PARTIAL_INIT;
1660  return \"addu %2,%1,%0\";
1661}")
1662
1663(define_insn "adddi3"
1664  [(set (match_operand:DI 0 "register_operand" "=f")
1665	(plus:DI (match_operand:DI 1 "register_operand" "%f")
1666		 (match_operand:DI 2 "register_operand" "f")))]
1667  ""
1668  "fiadd.dd %1,%2,%0")
1669
1670(define_insn "subsi3"
1671  [(set (match_operand:SI 0 "register_operand" "=r,r,*f")
1672	(minus:SI (match_operand:SI 1 "register_operand" "r,I,*f")
1673		  (match_operand:SI 2 "arith_operand" "rI,r,*f")))]
1674  ""
1675  "*
1676{
1677  if (which_alternative == 2)
1678    return \"fisub.ss %1,%2,%0\";
1679  CC_STATUS_PARTIAL_INIT;
1680  if (REG_P (operands[2]))
1681    return \"subu %1,%2,%0\";
1682  operands[2] = GEN_INT (- INTVAL (operands[2]));
1683  return \"addu %2,%1,%0\";
1684}")
1685
1686(define_insn "subdi3"
1687  [(set (match_operand:DI 0 "register_operand" "=f")
1688	(minus:DI (match_operand:DI 1 "register_operand" "f")
1689		  (match_operand:DI 2 "register_operand" "f")))]
1690  ""
1691  "fisub.dd %1,%2,%0")
1692
1693(define_expand "mulsi3"
1694  [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" ""))
1695   (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" ""))
1696   (clobber (match_dup 3))
1697   (set (subreg:SI (match_dup 3) 0)
1698	(mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0)))
1699   (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))]
1700  ""
1701  "
1702{
1703  if (WORDS_BIG_ENDIAN)
1704    emit_insn (gen_mulsi3_big (operands[0], operands[1], operands[2]));
1705  else
1706    emit_insn (gen_mulsi3_little (operands[0], operands[1], operands[2]));
1707  DONE;
1708}")
1709
1710(define_expand "mulsi3_little"
1711  [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" ""))
1712   (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" ""))
1713   (clobber (match_dup 3))
1714   (set (subreg:SI (match_dup 3) 0)
1715	(mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0)))
1716   (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))]
1717  "! WORDS_BIG_ENDIAN"
1718  "
1719{
1720  operands[3] = gen_reg_rtx (DImode);
1721  operands[4] = gen_reg_rtx (DImode);
1722  operands[5] = gen_reg_rtx (DImode);
1723}")
1724
1725(define_expand "mulsi3_big"
1726  [(set (subreg:SI (match_dup 4) 1) (match_operand:SI 1 "general_operand" ""))
1727   (set (subreg:SI (match_dup 5) 1) (match_operand:SI 2 "general_operand" ""))
1728   (clobber (match_dup 3))
1729   (set (subreg:SI (match_dup 3) 1)
1730	(mult:SI (subreg:SI (match_dup 4) 1) (subreg:SI (match_dup 5) 1)))
1731   (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 1))]
1732  "WORDS_BIG_ENDIAN"
1733  "
1734{
1735  operands[3] = gen_reg_rtx (DImode);
1736  operands[4] = gen_reg_rtx (DImode);
1737  operands[5] = gen_reg_rtx (DImode);
1738}")
1739
1740(define_insn ""
1741  [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 0)
1742	(mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0)
1743		 (subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))]
1744  "! WORDS_BIG_ENDIAN"
1745  "fmlow.dd %2,%1,%0")
1746
1747(define_insn ""
1748  [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 1)
1749	(mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 1)
1750		 (subreg:SI (match_operand:DI 2 "register_operand" "f") 1)))]
1751  "WORDS_BIG_ENDIAN"
1752  "fmlow.dd %2,%1,%0")
1753
1754;;- and instructions (with compliment also)			   
1755(define_insn "andsi3"
1756  [(set (match_operand:SI 0 "register_operand" "=r")
1757	(and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
1758		(match_operand:SI 2 "nonmemory_operand" "rL")))]
1759  ""
1760  "*
1761{
1762  rtx xop[3];
1763
1764  CC_STATUS_PARTIAL_INIT;
1765  if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
1766    return \"and %2,%1,%0\";
1767  if ((INTVAL (operands[2]) & 0xffff) == 0)
1768    {
1769      operands[2] = GEN_INT ((unsigned) INTVAL (operands[2]) >> 16);
1770      return \"andh %2,%1,%0\";
1771    }
1772  xop[0] = operands[0];
1773  xop[1] = operands[1];
1774  xop[2] = GEN_INT (~INTVAL (operands[2]) & 0xffff);
1775  output_asm_insn (\"andnot %2,%1,%0\", xop);
1776  operands[2] = GEN_INT (~(unsigned) INTVAL (operands[2]) >> 16);
1777  return \"andnoth %2,%0,%0\";
1778}")
1779
1780(define_insn ""
1781  [(set (match_operand:SI 0 "register_operand" "=r")
1782	(and:SI (not:SI (match_operand:SI 1 "register_operand" "rn"))
1783		(match_operand:SI 2 "register_operand" "r")))]
1784  ""
1785  "*
1786{
1787  rtx xop[3];
1788
1789  CC_STATUS_PARTIAL_INIT;
1790  if (REG_P (operands[1]) || LOGIC_INT (operands[1]))
1791    return \"andnot %1,%2,%0\";
1792  if ((INTVAL (operands[1]) & 0xffff) == 0)
1793    {
1794      operands[1] = GEN_INT ((unsigned) INTVAL (operands[1]) >> 16);
1795      return \"andnoth %1,%2,%0\";
1796    }
1797  xop[0] = operands[0];
1798  xop[1] = GEN_INT ((INTVAL (operands[1]) & 0xffff));
1799  xop[2] = operands[2];
1800  output_asm_insn (\"andnot %1,%2,%0\", xop);
1801  operands[1] = GEN_INT ((unsigned) INTVAL (operands[1]) >> 16);
1802  return \"andnoth %1,%0,%0\";
1803}")
1804
1805(define_insn "iorsi3"
1806  [(set (match_operand:SI 0 "register_operand" "=r")
1807	(ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
1808		(match_operand:SI 2 "nonmemory_operand" "rL")))]
1809  ""
1810  "*
1811{
1812  rtx xop[3];
1813
1814  CC_STATUS_PARTIAL_INIT;
1815  if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
1816    return \"or %2,%1,%0\";
1817  if ((INTVAL (operands[2]) & 0xffff) == 0)
1818    {
1819      operands[2] = GEN_INT ((unsigned) INTVAL (operands[2]) >> 16);
1820      return \"orh %2,%1,%0\";
1821    }
1822  xop[0] = operands[0];
1823  xop[1] = operands[1];
1824  xop[2] = GEN_INT ((INTVAL (operands[2]) & 0xffff));
1825  output_asm_insn (\"or %2,%1,%0\", xop);
1826  operands[2] = GEN_INT ((unsigned) INTVAL (operands[2]) >> 16);
1827  return \"orh %2,%0,%0\";
1828}")
1829
1830(define_insn "xorsi3"
1831  [(set (match_operand:SI 0 "register_operand" "=r")
1832	(xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
1833		(match_operand:SI 2 "nonmemory_operand" "rL")))]
1834  ""
1835  "*
1836{
1837  rtx xop[3];
1838
1839  CC_STATUS_PARTIAL_INIT;
1840  if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
1841    return \"xor %2,%1,%0\";
1842  if ((INTVAL (operands[2]) & 0xffff) == 0)
1843    {
1844      operands[2] = GEN_INT ((unsigned) INTVAL (operands[2]) >> 16);
1845      return \"xorh %2,%1,%0\";
1846    }
1847  xop[0] = operands[0];
1848  xop[1] = operands[1];
1849  xop[2] = GEN_INT ((INTVAL (operands[2]) & 0xffff));
1850  output_asm_insn (\"xor %2,%1,%0\", xop);
1851  operands[2] = GEN_INT ((unsigned) INTVAL (operands[2]) >> 16);
1852  return \"xorh %2,%0,%0\";
1853}")
1854
1855;(The i860 instruction set doesn't allow an immediate second operand in
1856; a subtraction.)
1857(define_insn "negsi2"
1858  [(set (match_operand:SI 0 "general_operand" "=r")
1859	(neg:SI (match_operand:SI 1 "arith_operand" "r")))]
1860  ""
1861  "*
1862{
1863  CC_STATUS_PARTIAL_INIT;
1864  return \"subu %?r0,%1,%0\";
1865}")
1866
1867(define_insn "one_cmplsi2"
1868  [(set (match_operand:SI 0 "general_operand" "=r")
1869	(not:SI (match_operand:SI 1 "arith_operand" "r")))]
1870  ""
1871  "*
1872{
1873  CC_STATUS_PARTIAL_INIT;
1874  return \"subu -1,%1,%0\";
1875}")
1876
1877;; Floating point arithmetic instructions.
1878
1879(define_insn "adddf3"
1880  [(set (match_operand:DF 0 "register_operand" "=f")
1881	(plus:DF (match_operand:DF 1 "register_operand" "f")
1882		 (match_operand:DF 2 "register_operand" "f")))]
1883  ""
1884  "fadd.dd %1,%2,%0")
1885
1886(define_insn "addsf3"
1887  [(set (match_operand:SF 0 "register_operand" "=f")
1888	(plus:SF (match_operand:SF 1 "register_operand" "f")
1889		 (match_operand:SF 2 "register_operand" "f")))]
1890  ""
1891  "fadd.ss %1,%2,%0")
1892
1893(define_insn "subdf3"
1894  [(set (match_operand:DF 0 "register_operand" "=f")
1895	(minus:DF (match_operand:DF 1 "register_operand" "f")
1896		  (match_operand:DF 2 "register_operand" "f")))]
1897  ""
1898  "fsub.dd %1,%2,%0")
1899
1900(define_insn "subsf3"
1901  [(set (match_operand:SF 0 "register_operand" "=f")
1902	(minus:SF (match_operand:SF 1 "register_operand" "f")
1903		  (match_operand:SF 2 "register_operand" "f")))]
1904  ""
1905  "fsub.ss %1,%2,%0")
1906
1907(define_insn "muldf3"
1908  [(set (match_operand:DF 0 "register_operand" "=f")
1909	(mult:DF (match_operand:DF 1 "register_operand" "f")
1910		 (match_operand:DF 2 "register_operand" "f")))]
1911  ""
1912  "fmul.dd %1,%2,%0")
1913
1914(define_insn "mulsf3"
1915  [(set (match_operand:SF 0 "register_operand" "=f")
1916	(mult:SF (match_operand:SF 1 "register_operand" "f")
1917		 (match_operand:SF 2 "register_operand" "f")))]
1918  ""
1919  "fmul.ss %1,%2,%0")
1920
1921(define_insn "negdf2"
1922  [(set (match_operand:DF 0 "register_operand" "=f")
1923	(neg:DF (match_operand:DF 1 "register_operand" "f")))]
1924  ""
1925  "fsub.dd %?f0,%1,%0")
1926
1927(define_insn "negsf2"
1928  [(set (match_operand:SF 0 "register_operand" "=f")
1929	(neg:SF (match_operand:SF 1 "register_operand" "f")))]
1930  ""
1931  "fsub.ss %?f0,%1,%0")
1932
1933(define_insn "divdf3"
1934  [(set (match_operand:DF 0 "register_operand" "=&f")
1935	(div:DF (match_operand:DF 1 "register_operand" "f")
1936		 (match_operand:DF 2 "register_operand" "f")))
1937   (clobber (match_scratch:DF 3 "=&f"))
1938   (clobber (match_scratch:DF 4 "=&f"))]
1939  ""
1940  "*
1941{
1942  CC_STATUS_PARTIAL_INIT;
1943  if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0)
1944      || (cc_prev_status.flags & CC_HI_R31_ADJ)
1945      || (cc_prev_status.mdep != CONST2_RTX (SFmode)))
1946    {
1947      cc_status.flags |= CC_KNOW_HI_R31;
1948      cc_status.flags &= ~CC_HI_R31_ADJ;
1949      cc_status.mdep = CONST2_RTX (SFmode); 
1950      return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\\
1951orh 0x4000,%?r0,%?r31\;ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\\
1952fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
1953fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
1954fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\";
1955    }
1956  else
1957    return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\\
1958ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\\
1959fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
1960fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
1961fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\";
1962}")
1963
1964(define_insn "divsf3"
1965  [(set (match_operand:SF 0 "register_operand" "=&f")
1966	(div:SF (match_operand:SF 1 "register_operand" "f")
1967		 (match_operand:SF 2 "register_operand" "f")))
1968   (clobber (match_scratch:SF 3 "=&f"))
1969   (clobber (match_scratch:SF 4 "=&f"))]
1970  ""
1971  "*
1972{
1973  CC_STATUS_PARTIAL_INIT;
1974  if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0)
1975      || (cc_prev_status.flags & CC_HI_R31_ADJ)
1976      || (cc_prev_status.mdep != CONST2_RTX (SFmode)))
1977    {
1978      cc_status.flags |= CC_KNOW_HI_R31;
1979      cc_status.flags &= ~CC_HI_R31_ADJ;
1980      cc_status.mdep = CONST2_RTX (SFmode);
1981      output_asm_insn (\"orh 0x4000,%?r0,%?r31\", operands);
1982    }
1983  return \"ixfr %?r31,%4\;frcp.ss %2,%0\;\\\
1984fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;fmul.ss %0,%3,%0\;\\\
1985fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;\\\
1986fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
1987}")
1988
1989;; Shift instructions
1990
1991;; Optimized special case of shifting.
1992;; Must precede the general case.
1993
1994(define_insn ""
1995  [(set (match_operand:SI 0 "register_operand" "=r")
1996	(ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
1997		     (const_int 24)))]
1998  ""
1999  "*
2000{
2001  if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
2002    {
2003      CC_STATUS_INIT;
2004      cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
2005      cc_status.mdep = XEXP (operands[1], 0);
2006      return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
2007    }
2008  return \"ld.b %1,%0\";
2009}")
2010
2011
2012;;- arithmetic shift instructions
2013(define_insn "ashlsi3"
2014  [(set (match_operand:SI 0 "register_operand" "=r")
2015	(ashift:SI (match_operand:SI 1 "register_operand" "r")
2016		   (match_operand:SI 2 "shift_operand" "rn")))]
2017  ""
2018  "*
2019{
2020  return \"shl %2,%1,%0\";
2021}")
2022
2023(define_insn "ashlhi3"
2024  [(set (match_operand:HI 0 "register_operand" "=r")
2025	(ashift:HI (match_operand:HI 1 "register_operand" "r")
2026		   (match_operand:HI 2 "shift_operand" "rn")))]
2027  ""
2028  "*
2029{
2030  return \"shl %2,%1,%0\";
2031}")
2032
2033(define_insn "ashlqi3"
2034  [(set (match_operand:QI 0 "register_operand" "=r")
2035	(ashift:QI (match_operand:QI 1 "register_operand" "r")
2036		   (match_operand:QI 2 "shift_operand" "rn")))]
2037  ""
2038  "*
2039{
2040  return \"shl %2,%1,%0\";
2041}")
2042
2043(define_insn "ashrsi3"
2044  [(set (match_operand:SI 0 "register_operand" "=r")
2045	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
2046		     (match_operand:SI 2 "shift_operand" "rn")))]
2047  ""
2048  "*
2049{
2050  return \"shra %2,%1,%0\";
2051}")
2052
2053(define_insn "lshrsi3"
2054  [(set (match_operand:SI 0 "register_operand" "=r")
2055	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
2056		     (match_operand:SI 2 "shift_operand" "rn")))]
2057  ""
2058  "*
2059{
2060  return \"shr %2,%1,%0\";
2061}")
2062
2063;; Unconditional and other jump instructions
2064
2065(define_insn "jump"
2066  [(set (pc) (label_ref (match_operand 0 "" "")))]
2067  ""
2068  "*
2069{
2070  return \"br %l0\;nop\";
2071}")
2072
2073;; Here are two simple peepholes which fill the delay slot of
2074;; an unconditional branch.
2075
2076(define_peephole
2077  [(set (match_operand:SI 0 "register_operand" "=rf")
2078	(match_operand:SI 1 "single_insn_src_p" "gfG"))
2079   (set (pc) (label_ref (match_operand 2 "" "")))]
2080  ""
2081  "* return output_delayed_branch (\"br %l2\", operands, insn);")
2082
2083(define_peephole
2084  [(set (match_operand:SI 0 "memory_operand" "=m")
2085	(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
2086   (set (pc) (label_ref (match_operand 2 "" "")))]
2087  ""
2088  "* return output_delayed_branch (\"br %l2\", operands, insn);")
2089
2090(define_insn "tablejump"
2091  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
2092   (use (label_ref (match_operand 1 "" "")))]
2093  ""
2094  "bri %0\;nop")
2095
2096(define_peephole
2097  [(set (match_operand:SI 0 "memory_operand" "=m")
2098	(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
2099   (set (pc) (match_operand:SI 2 "register_operand" "r"))
2100   (use (label_ref (match_operand 3 "" "")))]
2101  ""
2102  "* return output_delayed_branch (\"bri %2\", operands, insn);")
2103
2104;;- jump to subroutine
2105(define_expand "call"
2106  [(call (match_operand:SI 0 "memory_operand" "m")
2107	 (match_operand 1 "" "i"))]
2108  ;; operand[2] is next_arg_register
2109  ""
2110  "
2111{
2112  /* Make sure the address is just one reg and will stay that way.  */
2113  if (! call_insn_operand (operands[0], QImode))
2114    operands[0]
2115      = change_address (operands[0], VOIDmode,
2116			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
2117  if (INTVAL (operands[1]) > 0)
2118    {
2119      emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
2120      emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
2121    }
2122}")
2123
2124;;- jump to subroutine
2125(define_insn ""
2126  [(call (match_operand:SI 0 "call_insn_operand" "m")
2127	 (match_operand 1 "" "i"))]
2128  ;; operand[2] is next_arg_register
2129  ""
2130  "*
2131{
2132  /* strip the MEM.  */
2133  operands[0] = XEXP (operands[0], 0);
2134  CC_STATUS_INIT;
2135  if (GET_CODE (operands[0]) == REG)
2136    return \"calli %0\;nop\";
2137  return \"call %0\;nop\";
2138}")
2139
2140(define_peephole
2141  [(set (match_operand:SI 0 "register_operand" "=rf")
2142	(match_operand:SI 1 "single_insn_src_p" "gfG"))
2143   (call (match_operand:SI 2 "memory_operand" "m")
2144	 (match_operand 3 "" "i"))]
2145  ;;- Don't use operand 1 for most machines.
2146  "! reg_mentioned_p (operands[0], operands[2])"
2147  "*
2148{
2149  /* strip the MEM.  */
2150  operands[2] = XEXP (operands[2], 0);
2151  if (GET_CODE (operands[2]) == REG)
2152    return output_delayed_branch (\"calli %2\", operands, insn);
2153  return output_delayed_branch (\"call %2\", operands, insn);
2154}")
2155
2156(define_peephole
2157  [(set (match_operand:SI 0 "memory_operand" "=m")
2158	(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
2159   (call (match_operand:SI 2 "call_insn_operand" "m")
2160	 (match_operand 3 "" "i"))]
2161  ;;- Don't use operand 1 for most machines.
2162  ""
2163  "*
2164{
2165  /* strip the MEM.  */
2166  operands[2] = XEXP (operands[2], 0);
2167  if (GET_CODE (operands[2]) == REG)
2168    return output_delayed_branch (\"calli %2\", operands, insn);
2169  return output_delayed_branch (\"call %2\", operands, insn);
2170}")
2171
2172(define_expand "call_value"
2173  [(set (match_operand 0 "register_operand" "=rf")
2174	(call (match_operand:SI 1 "memory_operand" "m")
2175	      (match_operand 2 "" "i")))]
2176  ;; operand 3 is next_arg_register
2177  ""
2178  "
2179{
2180  /* Make sure the address is just one reg and will stay that way.  */
2181  if (! call_insn_operand (operands[1], QImode))
2182    operands[1]
2183      = change_address (operands[1], VOIDmode,
2184			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
2185  if (INTVAL (operands[2]) > 0)
2186    {
2187      emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
2188      emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
2189    }
2190}")
2191
2192(define_insn ""
2193  [(set (match_operand 0 "register_operand" "=rf")
2194	(call (match_operand:SI 1 "call_insn_operand" "m")
2195	      (match_operand 2 "" "i")))]
2196  ;; operand 3 is next_arg_register
2197  ""
2198  "*
2199{
2200  /* strip the MEM.  */
2201  operands[1] = XEXP (operands[1], 0);
2202  CC_STATUS_INIT;
2203  if (GET_CODE (operands[1]) == REG)
2204    return \"calli %1\;nop\";
2205  return \"call %1\;nop\";
2206}")
2207
2208(define_peephole
2209  [(set (match_operand:SI 0 "register_operand" "=rf")
2210	(match_operand:SI 1 "single_insn_src_p" "gfG"))
2211   (set (match_operand 2 "" "=rf")
2212	(call (match_operand:SI 3 "call_insn_operand" "m")
2213	      (match_operand 4 "" "i")))]
2214  ;;- Don't use operand 4 for most machines.
2215  "! reg_mentioned_p (operands[0], operands[3])"
2216  "*
2217{
2218  /* strip the MEM.  */
2219  operands[3] = XEXP (operands[3], 0);
2220  if (GET_CODE (operands[3]) == REG)
2221    return output_delayed_branch (\"calli %3\", operands, insn);
2222  return output_delayed_branch (\"call %3\", operands, insn);
2223}")
2224
2225(define_peephole
2226  [(set (match_operand:SI 0 "memory_operand" "=m")
2227	(match_operand:SI 1 "reg_or_0_operand" "rJf"))
2228   (set (match_operand 2 "" "=rf")
2229	(call (match_operand:SI 3 "call_insn_operand" "m")
2230	      (match_operand 4 "" "i")))]
2231  ;;- Don't use operand 4 for most machines.
2232  ""
2233  "*
2234{
2235  /* strip the MEM.  */
2236  operands[3] = XEXP (operands[3], 0);
2237  if (GET_CODE (operands[3]) == REG)
2238    return output_delayed_branch (\"calli %3\", operands, insn);
2239  return output_delayed_branch (\"call %3\", operands, insn);
2240}")
2241
2242;; Call subroutine returning any type.
2243
2244(define_expand "untyped_call"
2245  [(parallel [(call (match_operand 0 "" "")
2246		    (const_int 0))
2247	      (match_operand 1 "" "")
2248	      (match_operand 2 "" "")])]
2249  ""
2250  "
2251{
2252  int i;
2253
2254  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2255
2256  for (i = 0; i < XVECLEN (operands[2], 0); i++)
2257    {
2258      rtx set = XVECEXP (operands[2], 0, i);
2259      emit_move_insn (SET_DEST (set), SET_SRC (set));
2260    }
2261
2262  /* The optimizer does not know that the call sets the function value
2263     registers we stored in the result block.  We avoid problems by
2264     claiming that all hard registers are used and clobbered at this
2265     point.  */
2266  emit_insn (gen_blockage ());
2267
2268  DONE;
2269}")
2270
2271;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
2272;; all of memory.  This blocks insns from being moved across this point.
2273
2274(define_insn "blockage"
2275  [(unspec_volatile [(const_int 0)] 0)]
2276  ""
2277  "")
2278
2279(define_insn "nop"
2280  [(const_int 0)]
2281  ""
2282  "nop")
2283
2284(define_insn "indirect_jump"
2285  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
2286  ""
2287  "bri %0")
2288
2289;;
2290;; A special insn that does the work to get setup just
2291;; before a table jump.
2292;;
2293(define_insn ""
2294  [(set (match_operand:SI 0 "register_operand" "=r")
2295	(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
2296			 (label_ref (match_operand 2 "" "")))))]
2297  ""
2298  "*
2299{
2300  CC_STATUS_INIT;
2301  return \"orh %H2,%?r0,%?r31\;or %L2,%?r31,%?r31\;ld.l %?r31(%1),%0\";
2302}")
2303  
2304(define_peephole
2305  [(set (match_operand:SI 0 "register_operand" "=rf")
2306	(match_operand:SI 1 "single_insn_src_p" "gfG"))
2307   (set (pc) (match_operand:SI 2 "register_operand" "r"))
2308   (use (label_ref (match_operand 3 "" "")))]
2309  "REGNO (operands[0]) != REGNO (operands[2])"
2310  "* return output_delayed_branch (\"bri %2\", operands, insn);")
2311