FSF GCC merge 02/23/03
[official-gcc.git] / gcc / config / mmix / mmix.md
blobdc7148f39d3b6743a5da3e514f840c70b3bf4eeb
1 ;; GCC machine description for MMIX
2 ;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING.  If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
22 ;; The original PO technology requires these to be ordered by speed,
23 ;; so that assigner will pick the fastest.
25 ;; See file "rtl.def" for documentation on define_insn, match_*, et al.
27 ;; Uses of UNSPEC in this file:
28 ;; UNSPEC_VOLATILE:
30 ;;      0       sync_icache (sync icache before trampoline jump)
31 ;;      1       nonlocal_goto_receiver
34 ;; The order of insns is as in Node: Standard Names, with smaller modes
35 ;; before bigger modes.
37 (define_constants
38   [(MMIX_rJ_REGNUM 259)
39    (MMIX_rR_REGNUM 260)
40    (MMIX_fp_rO_OFFSET -24)]
43 ;; FIXME: Can we remove the reg-to-reg for smaller modes?  Shouldn't they
44 ;; be synthesized ok?
45 (define_insn "movqi"
46   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
47         (match_operand:QI 1 "general_operand"       "r,LS,K,rI,x,m,r,n"))]
48   ""
49   "@
50    SET %0,%1
51    %s1 %0,%v1
52    NEGU %0,0,%n1
53    PUT %0,%1
54    GET %0,%1
55    LDB%U0 %0,%1
56    STBU %1,%0
57    %r0%I1")
59 (define_insn "movhi"
60   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
61         (match_operand:HI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
62   ""
63   "@
64    SET %0,%1
65    %s1 %0,%v1
66    NEGU %0,0,%n1
67    PUT %0,%1
68    GET %0,%1
69    LDW%U0 %0,%1
70    STWU %1,%0
71    %r0%I1")
73 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
74 (define_insn "movsi"
75   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
76         (match_operand:SI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
77   ""
78   "@
79    SET %0,%1
80    %s1 %0,%v1
81    NEGU %0,0,%n1
82    PUT %0,%1
83    GET %0,%1
84    LDT%U0 %0,%1
85    STTU %1,%0
86    %r0%I1")
88 ;; We assume all "s" are addresses.  Does that hold?
89 (define_insn "movdi"
90   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
91         (match_operand:DI 1 "general_operand"       "r,LS,K,r,x,I,m,r,R,s,n"))]
92   ""
93   "@
94    SET %0,%1
95    %s1 %0,%v1
96    NEGU %0,0,%n1
97    PUT %0,%1
98    GET %0,%1
99    STCO %1,%0
100    LDO %0,%1
101    STOU %1,%0
102    GETA %0,%1
103    LDA %0,%1
104    %r0%I1")
106 ;; Note that we move around the float as a collection of bits; no
107 ;; conversion to double.
108 (define_insn "movsf"
109  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
110        (match_operand:SF 1 "general_operand"       "r,G,r,x,m,r,F"))]
111   ""
112   "@
113    SET %0,%1
114    SETL %0,0
115    PUT %0,%1
116    GET %0,%1
117    LDT %0,%1
118    STTU %1,%0
119    %r0%I1")
121 (define_insn "movdf"
122   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
123         (match_operand:DF 1 "general_operand"       "r,G,r,x,m,r,F"))]
124   ""
125   "@
126    SET %0,%1
127    SETL %0,0
128    PUT %0,%1
129    GET %0,%1
130    LDO %0,%1
131    STOU %1,%0
132    %r0%I1")
134 (define_insn "adddi3"
135   [(set (match_operand:DI 0 "register_operand"  "=r,r,r")
136         (plus:DI
137          (match_operand:DI 1 "register_operand" "%r,r,0")
138          (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
139   ""
140   "@
141    ADDU %0,%1,%2
142    SUBU %0,%1,%n2
143    %i2 %0,%v2")
145 (define_insn "adddf3"
146   [(set (match_operand:DF 0 "register_operand" "=r")
147         (plus:DF (match_operand:DF 1 "register_operand" "%r")
148                  (match_operand:DF 2 "register_operand" "r")))]
149   ""
150   "FADD %0,%1,%2")
152 ;; Insn canonicalization *should* have removed the need for an integer
153 ;; in operand 2.
154 (define_insn "subdi3"
155   [(set (match_operand:DI 0 "register_operand" "=r,r")
156         (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
157                   (match_operand:DI 2 "register_operand" "r,r")))]
158   ""
159   "@
160    SUBU %0,%1,%2
161    NEGU %0,%1,%2")
163 (define_insn "subdf3"
164   [(set (match_operand:DF 0 "register_operand" "=r")
165         (minus:DF (match_operand:DF 1 "register_operand" "r")
166                   (match_operand:DF 2 "register_operand" "r")))]
167   ""
168   "FSUB %0,%1,%2")
170 ;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
171 ;; %{something}2ADDU %0,%1,0)?  Hopefully GCC should still handle it, so
172 ;; we don't have to taint the machine description.  If results are bad
173 ;; enough, we may have to do it anyway.
174 (define_insn "muldi3"
175   [(set (match_operand:DI 0 "register_operand" "=r,r")
176         (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
177                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
178    (clobber (match_scratch:DI 3 "=X,z"))]
179   ""
180   "@
181    %m2ADDU %0,%1,%1
182    MULU %0,%1,%2")
184 (define_insn "muldf3"
185   [(set (match_operand:DF 0 "register_operand" "=r")
186         (mult:DF (match_operand:DF 1 "register_operand" "r")
187                  (match_operand:DF 2 "register_operand" "r")))]
188   ""
189   "FMUL %0,%1,%2")
191 (define_insn "divdf3"
192   [(set (match_operand:DF 0 "register_operand" "=r")
193         (div:DF (match_operand:DF 1 "register_operand" "r")
194                 (match_operand:DF 2 "register_operand" "r")))]
195   ""
196   "FDIV %0,%1,%2")
198 ;; FIXME: Is "frem" doing the right operation for moddf3?
199 (define_insn "moddf3"
200   [(set (match_operand:DF 0 "register_operand" "=r")
201         (mod:DF (match_operand:DF 1 "register_operand" "r")
202                 (match_operand:DF 2 "register_operand" "r")))]
203   ""
204   "FREM %0,%1,%2")
206 ;; FIXME: Should we define_expand for smin, smax, umin, umax using a
207 ;; nifty conditional sequence?
209 ;; FIXME: The cuter andn combinations don't get here, presumably because
210 ;; they ended up in the constant pool.  Check: still?
211 (define_insn "anddi3"
212   [(set (match_operand:DI 0 "register_operand" "=r,r")
213         (and:DI
214          (match_operand:DI 1 "register_operand" "%r,0")
215          (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
216   ""
217   "@
218    AND %0,%1,%2
219    %A2 %0,%V2")
221 (define_insn "iordi3"
222   [(set (match_operand:DI 0 "register_operand" "=r,r")
223         (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
224                 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rH,LS")))]
225   ""
226   "@
227    OR %0,%1,%2
228    %o2 %0,%v2")
230 (define_insn "xordi3"
231   [(set (match_operand:DI 0 "register_operand" "=r")
232         (xor:DI (match_operand:DI 1 "register_operand" "%r")
233                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
234   ""
235   "XOR %0,%1,%2")
237 ;; FIXME:  When TImode works for other reasons (like cross-compiling from
238 ;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
240 ;; FIXME: Check what's really reasonable for the mod part.
242 ;; One day we might persuade GCC to expand divisions with constants the
243 ;; way MMIX does; giving the remainder the sign of the divisor.  But even
244 ;; then, it might be good to have an option to divide the way "everybody
245 ;; else" does.  Perhaps then, this option can be on by default.  However,
246 ;; it's not likely to happen because major (C, C++, Fortran) language
247 ;; standards in effect at 2002-04-29 reportedly demand that the sign of
248 ;; the remainder must follow the sign of the dividend.
250 (define_insn "divmoddi4"
251   [(set (match_operand:DI 0 "register_operand" "=r")
252         (div:DI (match_operand:DI 1 "register_operand" "r")
253                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
254    (set (match_operand:DI 3 "register_operand" "=y")
255         (mod:DI (match_dup 1) (match_dup 2)))]
256   ;; Do the library stuff later.
257   "TARGET_KNUTH_DIVISION"
258   "DIV %0,%1,%2")
260 (define_insn "udivmoddi4"
261   [(set (match_operand:DI 0 "register_operand" "=r")
262         (udiv:DI (match_operand:DI 1 "register_operand" "r")
263                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
264    (set (match_operand:DI 3 "register_operand" "=y")
265         (umod:DI (match_dup 1) (match_dup 2)))]
266   ""
267   "DIVU %0,%1,%2")
269 (define_expand "divdi3"
270   [(parallel
271     [(set (match_operand:DI 0 "register_operand" "=&r")
272           (div:DI (match_operand:DI 1 "register_operand" "r")
273                   (match_operand:DI 2 "register_operand" "r")))
274      (clobber (scratch:DI))
275      (clobber (scratch:DI))
276      (clobber (reg:DI MMIX_rR_REGNUM))])]
277   "! TARGET_KNUTH_DIVISION"
278   "")
280 ;; The %2-is-%1-case is there just to make sure things don't fail.  Could
281 ;; presumably happen with optimizations off; no evidence.
282 (define_insn "*divdi3_nonknuth"
283   [(set (match_operand:DI 0 "register_operand" "=&r,r")
284         (div:DI (match_operand:DI 1 "register_operand" "r,r")
285                 (match_operand:DI 2 "register_operand" "1,r")))
286    (clobber (match_scratch:DI 3 "=1,1"))
287    (clobber (match_scratch:DI 4 "=2,2"))
288    (clobber (reg:DI MMIX_rR_REGNUM))]
289   "! TARGET_KNUTH_DIVISION"
290   "@
291    SETL %0,1
292    XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
293 DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
295 (define_expand "moddi3"
296   [(parallel
297     [(set (match_operand:DI 0 "register_operand" "=&r")
298           (mod:DI (match_operand:DI 1 "register_operand" "r")
299                   (match_operand:DI 2 "register_operand" "r")))
300      (clobber (scratch:DI))
301      (clobber (scratch:DI))
302      (clobber (reg:DI MMIX_rR_REGNUM))])]
303   "! TARGET_KNUTH_DIVISION"
304   "")
306 ;; The %2-is-%1-case is there just to make sure things don't fail.  Could
307 ;; presumably happen with optimizations off; no evidence.
308 (define_insn "*moddi3_nonknuth"
309   [(set (match_operand:DI 0 "register_operand" "=&r,r")
310         (mod:DI (match_operand:DI 1 "register_operand" "r,r")
311                 (match_operand:DI 2 "register_operand" "1,r")))
312    (clobber (match_scratch:DI 3 "=1,1"))
313    (clobber (match_scratch:DI 4 "=2,2"))
314    (clobber (reg:DI MMIX_rR_REGNUM))]
315   "! TARGET_KNUTH_DIVISION"
316   "@
317    SETL %0,0
318    NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
319 DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
321 (define_insn "ashldi3"
322   [(set (match_operand:DI 0 "register_operand" "=r")
323         (ashift:DI
324          (match_operand:DI 1 "register_operand" "r")
325          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
326   ""
327   "SLU %0,%1,%2")
329 (define_insn "ashrdi3"
330   [(set (match_operand:DI 0 "register_operand" "=r")
331         (ashiftrt:DI
332          (match_operand:DI 1 "register_operand" "r")
333          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
334   ""
335   "SR %0,%1,%2")
337 (define_insn "lshrdi3"
338   [(set (match_operand:DI 0 "register_operand" "=r")
339         (lshiftrt:DI
340          (match_operand:DI 1 "register_operand" "r")
341          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
342   ""
343   "SRU %0,%1,%2")
345 (define_insn "negdi2"
346   [(set (match_operand:DI 0 "register_operand" "=r")
347         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
348   ""
349   "NEGU %0,0,%1")
351 (define_expand "negdf2"
352   [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
353                    (neg:DF (match_operand:DF 1 "register_operand" "r")))
354               (use (match_dup 2))])]
355   ""
357   /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0.  */
358   operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
361 (define_insn "*expanded_negdf2"
362   [(set (match_operand:DF 0 "register_operand" "=r")
363         (neg:DF (match_operand:DF 1 "register_operand" "r")))
364    (use (match_operand:DI 2 "register_operand" "r"))]
365   ""
366   "XOR %0,%1,%2")
368 ;; FIXME: define_expand for absdi2?
370 (define_insn "absdf2"
371   [(set (match_operand:DF 0 "register_operand" "=r")
372         (abs:DF (match_operand:DF 1 "register_operand" "0")))]
373   ""
374   "ANDNH %0,#8000")
376 (define_insn "sqrtdf2"
377   [(set (match_operand:DF 0 "register_operand" "=r")
378         (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
379   ""
380   "FSQRT %0,%1")
382 ;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
384 (define_insn "one_cmpldi2"
385   [(set (match_operand:DI 0 "register_operand" "=r")
386         (not:DI (match_operand:DI 1 "register_operand" "r")))]
387   ""
388   "NOR %0,%1,0")
390 ;; Since we don't have cc0, we do what is recommended in the manual;
391 ;; store away the operands for use in the branch, scc or movcc insn.
392 (define_expand "cmpdi"
393   [(match_operand:DI 0 "register_operand" "")
394    (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")]
395   ""
396   "
398   mmix_compare_op0 = operands[0];
399   mmix_compare_op1 = operands[1];
400   DONE;
403 (define_expand "cmpdf"
404   [(match_operand:DF 0 "register_operand" "")
405    (match_operand:DF 1 "register_operand" "")]
406   ""
407   "
409   mmix_compare_op0 = operands[0];
410   mmix_compare_op1 = operands[1];
411   DONE;
414 ;; When the user-patterns expand, the resulting insns will match the
415 ;; patterns below.
417 ;; We can fold the signed-compare where the register value is
418 ;; already equal to (compare:CCTYPE (reg) (const_int 0)).
419 ;;  We can't do that at all for floating-point, due to NaN, +0.0
420 ;; and -0.0, and we can only do it for the non/zero test of
421 ;; unsigned, so that has to be done another way.
422 ;;  FIXME: Perhaps a peep2 changing CCcode to a new code, that
423 ;; gets folded here.
424 (define_insn "*cmpcc_folded"
425   [(set (match_operand:CC 0 "register_operand" "=r")
426         (compare:CC
427          (match_operand:DI 1 "register_operand" "r")
428          (const_int 0)))]
429   ;; FIXME: Can we test equivalence any other way?
430   ;; FIXME: Can we fold any other way?
431   "REGNO (operands[1]) == REGNO (operands[0])"
432   "%% folded: cmp %0,%1,0")
434 (define_insn "*cmpcc"
435   [(set (match_operand:CC 0 "register_operand" "=r")
436         (compare:CC
437          (match_operand:DI 1 "register_operand" "r")
438          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
439   ""
440   "CMP %0,%1,%2")
442 (define_insn "*cmpu"
443   [(set (match_operand:CC_UNS 0 "register_operand" "=r")
444         (compare:CC_UNS
445          (match_operand:DI 1 "register_operand" "r")
446          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
447   ""
448   "CMPU %0,%1,%2")
450 (define_insn "*fcmp"
451   [(set (match_operand:CC_FP 0 "register_operand" "=r")
452         (compare:CC_FP
453          (match_operand:DF 1 "register_operand" "r")
454          (match_operand:DF 2 "register_operand" "r")))]
455   ""
456   "FCMP%e0 %0,%1,%2")
458 ;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to
459 ;; make signalling compliant.
460 (define_insn "*feql"
461   [(set (match_operand:CC_FPEQ 0 "register_operand" "=r")
462         (compare:CC_FPEQ
463          (match_operand:DF 1 "register_operand" "r")
464          (match_operand:DF 2 "register_operand" "r")))]
465   ""
466   "FEQL%e0 %0,%1,%2")
468 (define_insn "*fun"
469   [(set (match_operand:CC_FUN 0 "register_operand" "=r")
470         (compare:CC_FUN
471          (match_operand:DF 1 "register_operand" "r")
472          (match_operand:DF 2 "register_operand" "r")))]
473   ""
474   "FUN%e0 %0,%1,%2")
476 ;; In order to get correct rounding, we have to use SFLOT and SFLOTU for
477 ;; conversion.  They do not convert to SFmode; they convert to DFmode,
478 ;; with rounding as of SFmode.  They are not usable as is, but we pretend
479 ;; we have a single instruction but emit two.
481 ;; Note that this will (somewhat unexpectedly) create an inexact
482 ;; exception if rounding is necessary - has to be masked off in crt0?
483 (define_expand "floatdisf2"
484   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
485                    (float:SF
486                     (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
487               ;; Let's use a DI scratch, since SF don't generally get into
488               ;; registers.  Dunno what's best; it's really a DF, but that
489               ;; doesn't logically follow from operands in the pattern.
490               (clobber (match_scratch:DI 2 "=&r"))])]
491   ""
492   "
494   if (GET_CODE (operands[0]) != MEM)
495     {
496       rtx stack_slot;
498       /* FIXME: This stack-slot remains even at -O3.  There must be a
499          better way.  */
500       stack_slot
501         = validize_mem (assign_stack_temp (SFmode,
502                                            GET_MODE_SIZE (SFmode), 0));
503       emit_insn (gen_floatdisf2 (stack_slot, operands[1]));
504       emit_move_insn (operands[0], stack_slot);
505       DONE;
506     }
509 (define_insn "*floatdisf2_real"
510   [(set (match_operand:SF 0 "memory_operand" "=m")
511         (float:SF
512          (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
513    (clobber (match_scratch:DI 2 "=&r"))]
514   ""
515   "SFLOT %2,%1\;STSF %2,%0")
517 (define_expand "floatunsdisf2"
518   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
519                    (unsigned_float:SF
520                     (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
521               ;; Let's use a DI scratch, since SF don't generally get into
522               ;; registers.  Dunno what's best; it's really a DF, but that
523               ;; doesn't logically follow from operands in the pattern.
524               (clobber (scratch:DI))])]
525   ""
526   "
528   if (GET_CODE (operands[0]) != MEM)
529     {
530       rtx stack_slot;
532       /* FIXME: This stack-slot remains even at -O3.  Must be a better
533          way.  */
534       stack_slot
535         = validize_mem (assign_stack_temp (SFmode,
536                                            GET_MODE_SIZE (SFmode), 0));
537       emit_insn (gen_floatunsdisf2 (stack_slot, operands[1]));
538       emit_move_insn (operands[0], stack_slot);
539       DONE;
540     }
543 (define_insn "*floatunsdisf2_real"
544   [(set (match_operand:SF 0 "memory_operand" "=m")
545         (unsigned_float:SF
546          (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
547    (clobber (match_scratch:DI 2 "=&r"))]
548   ""
549   "SFLOTU %2,%1\;STSF %2,%0")
551 ;; Note that this will (somewhat unexpectedly) create an inexact
552 ;; exception if rounding is necessary - has to be masked off in crt0?
553 (define_insn "floatdidf2"
554   [(set (match_operand:DF 0 "register_operand" "=r")
555         (float:DF
556          (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
557   ""
558   "FLOT %0,%1")
560 (define_insn "floatunsdidf2"
561   [(set (match_operand:DF 0 "register_operand" "=r")
562         (unsigned_float:DF
563          (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
564   ""
565   "FLOTU %0,%1")
567 (define_insn "ftruncdf2"
568   [(set (match_operand:DF 0 "register_operand" "=r")
569         (fix:DF (match_operand:DF 1 "register_operand" "r")))]
570   ""
571   ;; ROUND_OFF
572   "FINT %0,1,%1")
574 ;; Note that this will (somewhat unexpectedly) create an inexact
575 ;; exception if rounding is necessary - has to be masked off in crt0?
576 (define_insn "fix_truncdfdi2"
577   [(set (match_operand:DI 0 "register_operand" "=r")
578         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
579   ""
580   ;; ROUND_OFF
581   "FIX %0,1,%1")
583 (define_insn "fixuns_truncdfdi2"
584   [(set (match_operand:DI 0 "register_operand" "=r")
585         (unsigned_fix:DI
586          (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
587   ""
588   ;; ROUND_OFF
589   "FIXU %0,1,%1")
591 ;; It doesn't seem like it's possible to have memory_operand as a
592 ;; predicate here (testcase: libgcc2 floathisf).  FIXME:  Shouldn't it be
593 ;; possible to do that?  Bug in GCC?  Anyway, this used to be a simple
594 ;; pattern with a memory_operand predicate, but was split up with a
595 ;; define_expand with the old pattern as "anonymous".
596 ;; FIXME: Perhaps with SECONDARY_MEMORY_NEEDED?
597 (define_expand "truncdfsf2"
598   [(set (match_operand:SF 0 "memory_operand" "")
599         (float_truncate:SF (match_operand:DF 1 "register_operand" "")))]
600   ""
601   "
603   if (GET_CODE (operands[0]) != MEM)
604     {
605       /* FIXME: There should be a way to say: 'put this in operands[0]
606          but *after* the expanded insn'.  */
607       rtx stack_slot;
609       /* There is no sane destination but a register here, if it wasn't
610          already MEM.  (It's too hard to get fatal_insn to work here.)  */
611       if (! REG_P (operands[0]))
612         internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\");
614       /* FIXME: This stack-slot remains even at -O3.  Must be a better
615          way.  */
616       stack_slot
617         = validize_mem (assign_stack_temp (SFmode,
618                                            GET_MODE_SIZE (SFmode), 0));
619       emit_insn (gen_truncdfsf2 (stack_slot, operands[1]));
620       emit_move_insn (operands[0], stack_slot);
621       DONE;
622     }
625 (define_insn "*truncdfsf2_real"
626   [(set (match_operand:SF 0 "memory_operand" "=m")
627         (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
628   ""
629   "STSF %1,%0")
631 ;; Same comment as for truncdfsf2.
632 (define_expand "extendsfdf2"
633   [(set (match_operand:DF 0 "register_operand" "=r")
634         (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
635   ""
636   "
638   if (GET_CODE (operands[1]) != MEM)
639     {
640       rtx stack_slot;
642       /* There is no sane destination but a register here, if it wasn't
643          already MEM.  (It's too hard to get fatal_insn to work here.)  */
644       if (! REG_P (operands[0]))
645         internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\");
647       /* FIXME: This stack-slot remains even at -O3.  There must be a
648          better way.  */
649       stack_slot
650         = validize_mem (assign_stack_temp (SFmode,
651                                            GET_MODE_SIZE (SFmode), 0));
652       emit_move_insn (stack_slot, operands[1]);
653       emit_insn (gen_extendsfdf2 (operands[0], stack_slot));
654       DONE;
655     }
658 (define_insn "*extendsfdf2_real"
659   [(set (match_operand:DF 0 "register_operand" "=r")
660         (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
661   ""
662   "LDSF %0,%1")
664 ;; Neither sign-extend nor zero-extend are necessary; gcc knows how to
665 ;; synthesize using shifts or and, except with a memory source and not
666 ;; completely optimal.  FIXME: Actually, other bugs surface when those
667 ;; patterns are defined; fix later.
669 ;; There are no sane values with the bit-patterns of (int) 0..255 except
670 ;; 0 to use in movdfcc.
672 (define_expand "movdfcc"
673   [(set (match_operand:DF 0 "register_operand" "")
674         (if_then_else:DF
675          (match_operand 1 "comparison_operator" "")
676          (match_operand:DF 2 "mmix_reg_or_0_operand" "")
677          (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
678   ""
679   "
681   enum rtx_code code = GET_CODE (operands[1]);
682   rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
683                                      mmix_compare_op1);
684   if (cc_reg == NULL_RTX)
685     FAIL;
686   operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
689 (define_expand "movdicc"
690   [(set (match_operand:DI 0 "register_operand" "")
691         (if_then_else:DI
692          (match_operand 1 "comparison_operator" "")
693          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
694          (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
695   ""
696   "
698   enum rtx_code code = GET_CODE (operands[1]);
699   rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
700                                      mmix_compare_op1);
701   if (cc_reg == NULL_RTX)
702     FAIL;
703   operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
706 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
707 (define_insn "*movdicc_real_foldable"
708   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
709         (if_then_else:DI
710          (match_operator 2 "mmix_foldable_comparison_operator"
711                          [(match_operand 3 "register_operand" "r,r,r,r")
712                           (const_int 0)])
713          (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
714          (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
715   ""
716   "@
717    CS%d2 %0,%3,%1
718    CS%D2 %0,%3,%4
719    ZS%d2 %0,%3,%1
720    ZS%D2 %0,%3,%4")
722 (define_insn "*movdicc_real"
723   [(set
724     (match_operand:DI 0 "register_operand"         "=r ,r ,r ,r")
725     (if_then_else:DI
726      (match_operator
727       2 "mmix_comparison_operator"
728       [(match_operand 3 "mmix_reg_cc_operand"       "r ,r ,r ,r")
729       (const_int 0)])
730      (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
731      (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
732   ""
733   "@
734    CS%d2 %0,%3,%1
735    CS%D2 %0,%3,%4
736    ZS%d2 %0,%3,%1
737    ZS%D2 %0,%3,%4")
739 (define_insn "*movdfcc_real_foldable"
740   [(set
741     (match_operand:DF 0 "register_operand"      "=r  ,r  ,r  ,r")
742     (if_then_else:DF
743      (match_operator
744       2 "mmix_foldable_comparison_operator"
745       [(match_operand 3 "register_operand"       "r  ,r  ,r  ,r")
746       (const_int 0)])
747      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
748      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
749   ""
750   "@
751    CS%d2 %0,%3,%1
752    CS%D2 %0,%3,%4
753    ZS%d2 %0,%3,%1
754    ZS%D2 %0,%3,%4")
756 (define_insn "*movdfcc_real"
757   [(set
758     (match_operand:DF 0 "register_operand"      "=r  ,r  ,r  ,r")
759     (if_then_else:DF
760      (match_operator
761       2 "mmix_comparison_operator"
762       [(match_operand 3 "mmix_reg_cc_operand"    "r  ,r  ,r  ,r")
763       (const_int 0)])
764      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
765      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
766   ""
767   "@
768    CS%d2 %0,%3,%1
769    CS%D2 %0,%3,%4
770    ZS%d2 %0,%3,%1
771    ZS%D2 %0,%3,%4")
773 ;; FIXME: scc patterns will probably help, I just skip them
774 ;; right now.  Revisit.
776 (define_expand "beq"
777   [(set (pc)
778         (if_then_else (eq (match_dup 1) (const_int 0))
779                       (label_ref (match_operand 0 "" ""))
780                       (pc)))]
781   ""
782   "
784   operands[1]
785     = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1);
788 (define_expand "bne"
789   [(set (pc)
790         (if_then_else (ne (match_dup 1) (const_int 0))
791                       (label_ref (match_operand 0 "" ""))
792                       (pc)))]
793   ""
794   "
796   operands[1]
797     = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1);
800 (define_expand "bgt"
801   [(set (pc)
802         (if_then_else (gt (match_dup 1) (const_int 0))
803                       (label_ref (match_operand 0 "" ""))
804                       (pc)))]
805   ""
806   "
808   operands[1]
809     = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1);
812 (define_expand "ble"
813   [(set (pc)
814         (if_then_else (le (match_dup 1) (const_int 0))
815                       (label_ref (match_operand 0 "" ""))
816                       (pc)))]
817   ""
818   "
820   operands[1]
821     = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
823   /* The head comment of optabs.c:can_compare_p says we're required to
824      implement this, so we have to clean up the mess here. */
825   if (operands[1] == NULL_RTX)
826     {
827       /* FIXME: Watch out for sharing/unsharing of rtx:es.  */
828       emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0]));
829       emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
830       DONE;
831     }
834 (define_expand "bge"
835   [(set (pc)
836         (if_then_else (ge (match_dup 1) (const_int 0))
837                       (label_ref (match_operand 0 "" ""))
838                       (pc)))]
839   ""
840   "
842   operands[1]
843     = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
845   /* The head comment of optabs.c:can_compare_p says we're required to
846      implement this, so we have to clean up the mess here. */
847   if (operands[1] == NULL_RTX)
848     {
849       /* FIXME: Watch out for sharing/unsharing of rtx:es.  */
850       emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0]));
851       emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
852       DONE;
853     }
856 (define_expand "blt"
857   [(set (pc)
858         (if_then_else (lt (match_dup 1) (const_int 0))
859                       (label_ref (match_operand 0 "" ""))
860                       (pc)))]
861   ""
862   "
864   operands[1]
865     = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);
868 (define_expand "bgtu"
869   [(set (pc)
870         (if_then_else (gtu (match_dup 1) (const_int 0))
871                       (label_ref (match_operand 0 "" ""))
872                       (pc)))]
873   ""
874   "
876   operands[1]
877     = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);
880 (define_expand "bleu"
881   [(set (pc)
882         (if_then_else (leu (match_dup 1) (const_int 0))
883                       (label_ref (match_operand 0 "" ""))
884                       (pc)))]
885   ""
886   "
888   operands[1]
889     = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);
892 (define_expand "bgeu"
893   [(set (pc)
894         (if_then_else (geu (match_dup 1) (const_int 0))
895                       (label_ref (match_operand 0 "" ""))
896                       (pc)))]
897   ""
898   "
900   operands[1]
901     = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);
904 (define_expand "bltu"
905   [(set (pc)
906         (if_then_else (ltu (match_dup 1) (const_int 0))
907                       (label_ref (match_operand 0 "" ""))
908                       (pc)))]
909   ""
910   "
912   operands[1]
913     = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);
916 (define_expand "bunordered"
917   [(set (pc)
918         (if_then_else (unordered (match_dup 1) (const_int 0))
919                       (label_ref (match_operand 0 "" ""))
920                       (pc)))]
921   ""
922   "
924   operands[1]
925     = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1);
927   if (operands[1] == NULL_RTX)
928     FAIL;
931 (define_expand "bordered"
932   [(set (pc)
933         (if_then_else (ordered (match_dup 1) (const_int 0))
934                       (label_ref (match_operand 0 "" ""))
935                       (pc)))]
936   ""
937   "
939   operands[1]
940     = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);
943 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
944 ;; there's no RTL code for it.  Maybe revisit in future.
946 ;; FIXME: Odd/Even matchers?
947 (define_insn "*bCC_foldable"
948   [(set (pc)
949         (if_then_else
950          (match_operator 1 "mmix_foldable_comparison_operator"
951                          [(match_operand 2 "register_operand" "r")
952                           (const_int 0)])
953          (label_ref (match_operand 0 "" ""))
954          (pc)))]
955   ""
956   "%+B%d1 %2,%0")
958 (define_insn "*bCC"
959   [(set (pc)
960         (if_then_else
961          (match_operator 1 "mmix_comparison_operator"
962                          [(match_operand 2 "mmix_reg_cc_operand" "r")
963                           (const_int 0)])
964          (label_ref (match_operand 0 "" ""))
965          (pc)))]
966   ""
967   "%+B%d1 %2,%0")
969 (define_insn "*bCC_inverted_foldable"
970   [(set (pc)
971         (if_then_else
972          (match_operator 1 "mmix_foldable_comparison_operator"
973                          [(match_operand 2 "register_operand" "r")
974                           (const_int 0)])
975                       (pc)
976                       (label_ref (match_operand 0 "" ""))))]
977 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
978   ""
979   "%+B%D1 %2,%0")
981 (define_insn "*bCC_inverted"
982   [(set (pc)
983         (if_then_else
984          (match_operator 1 "mmix_comparison_operator"
985                          [(match_operand 2 "mmix_reg_cc_operand" "r")
986                           (const_int 0)])
987          (pc)
988          (label_ref (match_operand 0 "" ""))))]
989   "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
990   "%+B%D1 %2,%0")
992 (define_expand "call"
993   [(parallel [(call (match_operand:QI 0 "memory_operand" "")
994                     (match_operand 1 "general_operand" ""))
995               (use (match_operand 2 "general_operand" ""))
996               (clobber (match_dup 4))])
997    (set (match_dup 4) (match_dup 3))]
998   ""
999   "
1001   /* Since the epilogue 'uses' the return address, and it is clobbered
1002      in the call, and we set it back after every call (all but one setting
1003      will be optimized away), integrity is maintained.  */
1004   operands[3]
1005     = mmix_get_hard_reg_initial_val (Pmode,
1006                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1008   /* FIXME: There's a bug in gcc which causes NULL to be passed as
1009      operand[2] when we get out of registers, which later confuses gcc.
1010      Work around it by replacing it with const_int 0.  Possibly documentation
1011      error too.  */
1012   if (operands[2] == NULL_RTX)
1013     operands[2] = const0_rtx;
1015   operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1018 (define_expand "call_value"
1019   [(parallel [(set (match_operand 0 "" "")
1020                    (call (match_operand:QI 1 "memory_operand" "")
1021                          (match_operand 2 "general_operand" "")))
1022               (use (match_operand 3 "general_operand" ""))
1023               (clobber (match_dup 5))])
1024    (set (match_dup 5) (match_dup 4))]
1025   ""
1026   "
1028   /* Since the epilogue 'uses' the return address, and it is clobbered
1029      in the call, and we set it back after every call (all but one setting
1030      will be optimized away), integrity is maintained.  */
1031   operands[4]
1032     = mmix_get_hard_reg_initial_val (Pmode,
1033                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1035   /* FIXME: See 'call'.  */
1036   if (operands[3] == NULL_RTX)
1037     operands[3] = const0_rtx;
1039   /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
1040      *next* argument register, not the number of arguments in registers.
1041      (There used to be code here where that mattered.)  */
1043   operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1046 ;; Don't use 'p' here.  A 'p' must stand first in constraints, or reload
1047 ;; messes up, not registering the address for reload.  Several C++
1048 ;; test-cases, including g++.brendan/crash40.C.  FIXME: This is arguably a
1049 ;; bug in gcc.  Note line ~2612 in reload.c, that does things on the
1050 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1051 ;; ~3017 that says:
1052 ;; <<   case 'p':
1053 ;;           /* All necessary reloads for an address_operand
1054 ;;              were handled in find_reloads_address.  */>>
1055 ;; Sorry, I have not dug deeper.  If symbolic addresses are used
1056 ;; rarely compared to addresses in registers, disparaging the
1057 ;; first ("p") alternative by adding ? in the first operand
1058 ;; might do the trick.  We define 'U' as a synonym to 'p', but without the
1059 ;; caveats (and very small advantages) of 'p'.
1060 (define_insn "*call_real"
1061   [(call (mem:QI
1062           (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1063          (match_operand 1 "" ""))
1064    (use (match_operand 2 "" ""))
1065    (clobber (reg:DI MMIX_rJ_REGNUM))]
1066   ""
1067   "@
1068    PUSHJ $%p2,%0
1069    PUSHGO $%p2,%a0")
1071 (define_insn "*call_value_real"
1072   [(set (match_operand 0 "register_operand" "=r,r")
1073         (call (mem:QI
1074                (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1075               (match_operand 2 "" "")))
1076   (use (match_operand 3 "" ""))
1077   (clobber (reg:DI MMIX_rJ_REGNUM))]
1078   ""
1079   "@
1080    PUSHJ $%p3,%1
1081    PUSHGO $%p3,%a1")
1083 ;; I hope untyped_call and untyped_return are not needed for MMIX.
1084 ;; Users of Objective-C will notice.
1086 ; Generated by GCC.
1087 (define_expand "return"
1088   [(return)]
1089   "mmix_use_simple_return ()"
1090   "")
1092 ; Generated by the epilogue expander.
1093 (define_insn "*expanded_return"
1094   [(return)]
1095   ""
1096   "POP %.,0")
1098 (define_expand "prologue"
1099   [(const_int 0)]
1100   ""
1101   "mmix_expand_prologue (); DONE;")
1103 ; Note that the (return) from the expander itself is always the last insn
1104 ; in the epilogue.
1105 (define_expand "epilogue"
1106   [(return)]
1107   ""
1108   "mmix_expand_epilogue ();")
1110 (define_insn "nop"
1111   [(const_int 0)]
1112   ""
1113   "SWYM 0,0,0")
1115 (define_insn "jump"
1116   [(set (pc) (label_ref (match_operand 0 "" "")))]
1117   ""
1118   "JMP %0")
1120 (define_insn "indirect_jump"
1121   [(set (pc) (match_operand 0 "address_operand" "p"))]
1122   ""
1123   "GO $255,%a0")
1125 ;; FIXME: This is just a jump, and should be expanded to one.
1126 (define_insn "tablejump"
1127   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1128    (use (label_ref (match_operand 1 "" "")))]
1129   ""
1130   "GO $255,%a0")
1132 ;; The only peculiar thing is that the register stack has to be unwound at
1133 ;; nonlocal_goto_receiver.  At each function that has a nonlocal label, we
1134 ;; save at function entry the location of the "alpha" register stack
1135 ;; pointer, rO, in a stack slot known to that function (right below where
1136 ;; the frame-pointer would be located).
1137 ;; In the nonlocal goto receiver, we unwind the register stack by a series
1138 ;; of "pop 0,0" until rO equals the saved value.  (If it goes lower, we
1139 ;; should call abort.)
1140 (define_expand "nonlocal_goto_receiver"
1141   [(parallel [(unspec_volatile [(const_int 0)] 1)
1142               (clobber (scratch:DI))
1143               (clobber (reg:DI MMIX_rJ_REGNUM))])
1144    (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
1145   ""
1146   "
1148   operands[0]
1149     = mmix_get_hard_reg_initial_val (Pmode,
1150                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1152   /* Mark this function as containing a landing-pad.  */
1153   cfun->machine->has_landing_pad = 1;
1156 ;; GCC can insist on using saved registers to keep the slot address in
1157 ;; "across" the exception, or (perhaps) to use saved registers in the
1158 ;; address and re-use them after the register stack unwind, so it's best
1159 ;; to form the address ourselves.
1160 (define_insn "*nonlocal_goto_receiver_expanded"
1161   [(unspec_volatile [(const_int 0)] 1)
1162    (clobber (match_scratch:DI 0 "=&r"))
1163    (clobber (reg:DI MMIX_rJ_REGNUM))]
1164   ""
1166   rtx temp_reg = operands[0];
1167   rtx my_operands[2];
1168   HOST_WIDEST_INT offs;
1169   const char *my_template
1170     = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
1171 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1173   my_operands[1] = temp_reg;
1175   /* If we have a frame-pointer (hence unknown stack-pointer offset),
1176      just use the frame-pointer and the known offset.  */
1177   if (frame_pointer_needed)
1178     {
1179       my_operands[0] = GEN_INT (-MMIX_fp_rO_OFFSET);
1181       output_asm_insn ("NEGU %1,0,%0", my_operands);
1182       my_operands[0] = gen_rtx_PLUS (Pmode, frame_pointer_rtx, temp_reg);
1183     }
1184   else
1185     {
1186       /* We know the fp-based offset, so "eliminate" it to be sp-based.  */
1187       offs
1188         = (mmix_initial_elimination_offset (MMIX_FRAME_POINTER_REGNUM,
1189                                             MMIX_STACK_POINTER_REGNUM)
1190            + MMIX_fp_rO_OFFSET);
1192       if (offs >= 0 && offs <= 255)
1193         my_operands[0]
1194           = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1195       else
1196         {
1197           mmix_output_register_setting (asm_out_file, REGNO (temp_reg),
1198                                         offs, 1);
1199           my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, temp_reg);
1200         }
1201     }
1203   output_asm_insn (my_template, my_operands);
1204   return "";
1207 (define_insn "*Naddu"
1208   [(set (match_operand:DI 0 "register_operand" "=r")
1209         (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1210                           (match_operand:DI 2 "const_int_operand" "n"))
1211                  (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
1212   "GET_CODE (operands[2]) == CONST_INT
1213    && (INTVAL (operands[2]) == 2
1214        || INTVAL (operands[2]) == 4
1215        || INTVAL (operands[2]) == 8
1216        || INTVAL (operands[2]) == 16)"
1217   "%2ADDU %0,%1,%3")
1219 (define_insn "*andn"
1220   [(set (match_operand:DI 0 "register_operand" "=r")
1221         (and:DI
1222          (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1223          (match_operand:DI 2 "register_operand" "r")))]
1224   ""
1225   "ANDN %0,%2,%1")
1227 (define_insn "*nand"
1228   [(set (match_operand:DI 0 "register_operand" "=r")
1229         (ior:DI
1230          (not:DI (match_operand:DI 1 "register_operand" "%r"))
1231          (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1232   ""
1233   "NAND %0,%1,%2")
1235 (define_insn "*nor"
1236   [(set (match_operand:DI 0 "register_operand" "=r")
1237         (and:DI
1238          (not:DI (match_operand:DI 1 "register_operand" "%r"))
1239          (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1240   ""
1241   "NOR %0,%1,%2")
1243 (define_insn "*nxor"
1244   [(set (match_operand:DI 0 "register_operand" "=r")
1245         (not:DI
1246          (xor:DI (match_operand:DI 1 "register_operand" "%r")
1247                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1248   ""
1249   "NXOR %0,%1,%2")
1251 (define_insn "sync_icache"
1252   [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1253                      (match_operand:DI 1 "const_int_operand" "I")] 0)]
1254   ""
1255   "SYNCID %1,%0")
1257 ;; Local Variables:
1258 ;; mode: lisp
1259 ;; indent-tabs-mode: t
1260 ;; End: