OSDN Git Service

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