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