OSDN Git Service

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