OSDN Git Service

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