Revise -mdisable-fpregs option and add new -msoft-mult option
[official-gcc.git] / gcc / config / mmix / mmix.md
blob99be8263a1a1005a5ee9fb89ebcc256a85780a1c
1 ;; GCC machine description for MMIX
2 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
3 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; The original PO technology requires these to be ordered by speed,
22 ;; so that assigner will pick the fastest.
24 ;; See file "rtl.def" for documentation on define_insn, match_*, et al.
26 ;; Uses of UNSPEC in this file:
27 ;; UNSPEC_VOLATILE:
29 ;;      0       sync_icache (sync icache before trampoline jump)
30 ;;      1       nonlocal_goto_receiver
33 ;; The order of insns is as in Node: Standard Names, with smaller modes
34 ;; before bigger modes.
36 (define_constants
37   [(MMIX_rJ_REGNUM 259)
38    (MMIX_rR_REGNUM 260)
39    (MMIX_fp_rO_OFFSET -24)]
42 (define_mode_iterator MM [QI HI SI DI SF DF])
44 ;; Operand and operator predicates.
46 (include "predicates.md")
47 (include "constraints.md")
49 ;; FIXME: Can we remove the reg-to-reg for smaller modes?  Shouldn't they
50 ;; be synthesized ok?
51 (define_expand "mov<mode>"
52   [(set (match_operand:MM 0 "nonimmediate_operand")
53         (match_operand:MM 1 "general_operand"))]
54   ""
56   /*  Help pre-register-allocation to use at least one register in a move.
57       FIXME: support STCO also for DFmode (storing 0.0).  */
58   if (!REG_P (operands[0]) && !REG_P (operands[1])
59       && (<MODE>mode != DImode
60           || !memory_operand (operands[0], DImode)
61           || !satisfies_constraint_I (operands[1])))
62     operands[1] = force_reg (<MODE>mode, operands[1]);
65 (define_insn "*movqi_expanded"
66   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
67         (match_operand:QI 1 "general_operand"       "r,LS,K,rI,x,m,r,n"))]
68   "register_operand (operands[0], QImode)
69    || register_operand (operands[1], QImode)"
70   "@
71    SET %0,%1
72    %s1 %0,%v1
73    NEGU %0,0,%n1
74    PUT %0,%1
75    GET %0,%1
76    LDB%U0 %0,%1
77    STBU %1,%0
78    %r0%I1")
80 (define_insn "*movhi_expanded"
81   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
82         (match_operand:HI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
83   "register_operand (operands[0], HImode)
84    || register_operand (operands[1], HImode)"
85   "@
86    SET %0,%1
87    %s1 %0,%v1
88    NEGU %0,0,%n1
89    PUT %0,%1
90    GET %0,%1
91    LDW%U0 %0,%1
92    STWU %1,%0
93    %r0%I1")
95 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
96 (define_insn "*movsi_expanded"
97   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
98         (match_operand:SI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
99   "register_operand (operands[0], SImode)
100    || register_operand (operands[1], SImode)"
101   "@
102    SET %0,%1
103    %s1 %0,%v1
104    NEGU %0,0,%n1
105    PUT %0,%1
106    GET %0,%1
107    LDT%U0 %0,%1
108    STTU %1,%0
109    %r0%I1")
111 ;; We assume all "s" are addresses.  Does that hold?
112 (define_insn "*movdi_expanded"
113   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
114         (match_operand:DI 1 "general_operand"       "r,LS,K,r,x,I,m,r,R,s,n"))]
115   "register_operand (operands[0], DImode)
116    || register_operand (operands[1], DImode)
117    || (memory_operand (operands[0], DImode)
118        && satisfies_constraint_I (operands[1]))"
119   "@
120    SET %0,%1
121    %s1 %0,%v1
122    NEGU %0,0,%n1
123    PUT %0,%1
124    GET %0,%1
125    STCO %1,%0
126    LDO %0,%1
127    STOU %1,%0
128    GETA %0,%1
129    LDA %0,%1
130    %r0%I1")
132 ;; Note that we move around the float as a collection of bits; no
133 ;; conversion to double.
134 (define_insn "*movsf_expanded"
135  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
136        (match_operand:SF 1 "general_operand"       "r,G,r,x,m,r,F"))]
137   "register_operand (operands[0], SFmode)
138    || register_operand (operands[1], SFmode)"
139   "@
140    SET %0,%1
141    SETL %0,0
142    PUT %0,%1
143    GET %0,%1
144    LDT %0,%1
145    STTU %1,%0
146    %r0%I1")
148 (define_insn "*movdf_expanded"
149   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
150         (match_operand:DF 1 "general_operand"       "r,G,r,x,m,r,F"))]
151   "register_operand (operands[0], DFmode)
152    || register_operand (operands[1], DFmode)"
153   "@
154    SET %0,%1
155    SETL %0,0
156    PUT %0,%1
157    GET %0,%1
158    LDO %0,%1
159    STOU %1,%0
160    %r0%I1")
162 ;; We need to be able to move around the values used as condition codes.
163 ;; First spotted as reported in
164 ;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> due to
165 ;; changes in loop optimization.  The file machmode.def says they're of
166 ;; size 4 QI.  Valid bit-patterns correspond to integers -1, 0 and 1, so
167 ;; we treat them as signed entities; see mmix-modes.def.  The following
168 ;; expanders should cover all MODE_CC modes, and expand for this pattern.
169 (define_insn "*movcc_expanded"
170   [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
171         (match_operand 1 "nonimmediate_operand"  "r,r,x,m,r"))]
172   "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC
173    && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC"
174   "@
175    SET %0,%1
176    PUT %0,%1
177    GET %0,%1
178    LDT %0,%1
179    STT %1,%0")
181 (define_expand "movcc"
182   [(set (match_operand:CC 0 "nonimmediate_operand" "")
183         (match_operand:CC 1 "nonimmediate_operand" ""))]
184   ""
185   "")
187 (define_expand "movcc_uns"
188   [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
189         (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
190   ""
191   "")
193 (define_expand "movcc_fp"
194   [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
195         (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
196   ""
197   "")
199 (define_expand "movcc_fpeq"
200   [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
201         (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
202   ""
203   "")
205 (define_expand "movcc_fun"
206   [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
207         (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
208   ""
209   "")
211 (define_insn "adddi3"
212   [(set (match_operand:DI 0 "register_operand"  "=r,r,r")
213         (plus:DI
214          (match_operand:DI 1 "register_operand" "%r,r,0")
215          (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
216   ""
217   "@
218    ADDU %0,%1,%2
219    SUBU %0,%1,%n2
220    %i2 %0,%v2")
222 (define_insn "adddf3"
223   [(set (match_operand:DF 0 "register_operand" "=r")
224         (plus:DF (match_operand:DF 1 "register_operand" "%r")
225                  (match_operand:DF 2 "register_operand" "r")))]
226   ""
227   "FADD %0,%1,%2")
229 ;; Insn canonicalization *should* have removed the need for an integer
230 ;; in operand 2.
231 (define_insn "subdi3"
232   [(set (match_operand:DI 0 "register_operand" "=r,r")
233         (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
234                   (match_operand:DI 2 "register_operand" "r,r")))]
235   ""
236   "@
237    SUBU %0,%1,%2
238    NEGU %0,%1,%2")
240 (define_insn "subdf3"
241   [(set (match_operand:DF 0 "register_operand" "=r")
242         (minus:DF (match_operand:DF 1 "register_operand" "r")
243                   (match_operand:DF 2 "register_operand" "r")))]
244   ""
245   "FSUB %0,%1,%2")
247 ;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
248 ;; %{something}2ADDU %0,%1,0)?  Hopefully GCC should still handle it, so
249 ;; we don't have to taint the machine description.  If results are bad
250 ;; enough, we may have to do it anyway.
251 (define_insn "muldi3"
252   [(set (match_operand:DI 0 "register_operand" "=r,r")
253         (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
254                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
255    (clobber (match_scratch:DI 3 "=X,z"))]
256   ""
257   "@
258    %m2ADDU %0,%1,%1
259    MULU %0,%1,%2")
261 (define_insn "muldf3"
262   [(set (match_operand:DF 0 "register_operand" "=r")
263         (mult:DF (match_operand:DF 1 "register_operand" "r")
264                  (match_operand:DF 2 "register_operand" "r")))]
265   ""
266   "FMUL %0,%1,%2")
268 (define_insn "divdf3"
269   [(set (match_operand:DF 0 "register_operand" "=r")
270         (div:DF (match_operand:DF 1 "register_operand" "r")
271                 (match_operand:DF 2 "register_operand" "r")))]
272   ""
273   "FDIV %0,%1,%2")
275 ;; FIXME: Is "frem" doing the right operation for moddf3?
276 (define_insn "moddf3"
277   [(set (match_operand:DF 0 "register_operand" "=r")
278         (mod:DF (match_operand:DF 1 "register_operand" "r")
279                 (match_operand:DF 2 "register_operand" "r")))]
280   ""
281   "FREM %0,%1,%2")
283 ;; FIXME: Should we define_expand for smin, smax, umin, umax using a
284 ;; nifty conditional sequence?
286 ;; FIXME: The cuter andn combinations don't get here, presumably because
287 ;; they ended up in the constant pool.  Check: still?
288 (define_insn "anddi3"
289   [(set (match_operand:DI 0 "register_operand" "=r,r")
290         (and:DI
291          (match_operand:DI 1 "register_operand" "%r,0")
292          (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
293   ""
294   "@
295    AND %0,%1,%2
296    %A2 %0,%V2")
298 (define_insn "iordi3"
299   [(set (match_operand:DI 0 "register_operand" "=r,r")
300         (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
301                 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,LS")))]
302   ""
303   "@
304    OR %0,%1,%2
305    %o2 %0,%v2")
307 (define_insn "xordi3"
308   [(set (match_operand:DI 0 "register_operand" "=r")
309         (xor:DI (match_operand:DI 1 "register_operand" "%r")
310                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
311   ""
312   "XOR %0,%1,%2")
314 ;; FIXME:  When TImode works for other reasons (like cross-compiling from
315 ;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
317 ;; FIXME: Check what's really reasonable for the mod part.
319 ;; One day we might persuade GCC to expand divisions with constants the
320 ;; way MMIX does; giving the remainder the sign of the divisor.  But even
321 ;; then, it might be good to have an option to divide the way "everybody
322 ;; else" does.  Perhaps then, this option can be on by default.  However,
323 ;; it's not likely to happen because major (C, C++, Fortran) language
324 ;; standards in effect at 2002-04-29 reportedly demand that the sign of
325 ;; the remainder must follow the sign of the dividend.
327 (define_insn "divmoddi4"
328   [(set (match_operand:DI 0 "register_operand" "=r")
329         (div:DI (match_operand:DI 1 "register_operand" "r")
330                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
331    (set (match_operand:DI 3 "register_operand" "=y")
332         (mod:DI (match_dup 1) (match_dup 2)))]
333   ;; Do the library stuff later.
334   "TARGET_KNUTH_DIVISION"
335   "DIV %0,%1,%2")
337 (define_insn "udivmoddi4"
338   [(set (match_operand:DI 0 "register_operand" "=r")
339         (udiv:DI (match_operand:DI 1 "register_operand" "r")
340                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
341    (set (match_operand:DI 3 "register_operand" "=y")
342         (umod:DI (match_dup 1) (match_dup 2)))]
343   ""
344   "DIVU %0,%1,%2")
346 (define_expand "divdi3"
347   [(parallel
348     [(set (match_operand:DI 0 "register_operand" "=&r")
349           (div:DI (match_operand:DI 1 "register_operand" "r")
350                   (match_operand:DI 2 "register_operand" "r")))
351      (clobber (scratch:DI))
352      (clobber (scratch:DI))
353      (clobber (reg:DI MMIX_rR_REGNUM))])]
354   "! TARGET_KNUTH_DIVISION"
355   "")
357 ;; The %2-is-%1-case is there just to make sure things don't fail.  Could
358 ;; presumably happen with optimizations off; no evidence.
359 (define_insn "*divdi3_nonknuth"
360   [(set (match_operand:DI 0 "register_operand" "=&r,&r")
361         (div:DI (match_operand:DI 1 "register_operand" "r,r")
362                 (match_operand:DI 2 "register_operand" "1,r")))
363    (clobber (match_scratch:DI 3 "=1,1"))
364    (clobber (match_scratch:DI 4 "=2,2"))
365    (clobber (reg:DI MMIX_rR_REGNUM))]
366   "! TARGET_KNUTH_DIVISION"
367   "@
368    SETL %0,1
369    XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
370 DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
372 (define_expand "moddi3"
373   [(parallel
374     [(set (match_operand:DI 0 "register_operand" "=&r")
375           (mod:DI (match_operand:DI 1 "register_operand" "r")
376                   (match_operand:DI 2 "register_operand" "r")))
377      (clobber (scratch:DI))
378      (clobber (scratch:DI))
379      (clobber (reg:DI MMIX_rR_REGNUM))])]
380   "! TARGET_KNUTH_DIVISION"
381   "")
383 ;; The %2-is-%1-case is there just to make sure things don't fail.  Could
384 ;; presumably happen with optimizations off; no evidence.
385 (define_insn "*moddi3_nonknuth"
386   [(set (match_operand:DI 0 "register_operand" "=&r,&r")
387         (mod:DI (match_operand:DI 1 "register_operand" "r,r")
388                 (match_operand:DI 2 "register_operand" "1,r")))
389    (clobber (match_scratch:DI 3 "=1,1"))
390    (clobber (match_scratch:DI 4 "=2,2"))
391    (clobber (reg:DI MMIX_rR_REGNUM))]
392   "! TARGET_KNUTH_DIVISION"
393   "@
394    SETL %0,0
395    NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
396 DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
398 (define_insn "ashldi3"
399   [(set (match_operand:DI 0 "register_operand" "=r")
400         (ashift:DI
401          (match_operand:DI 1 "register_operand" "r")
402          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
403   ""
404   "SLU %0,%1,%2")
406 (define_insn "ashrdi3"
407   [(set (match_operand:DI 0 "register_operand" "=r")
408         (ashiftrt:DI
409          (match_operand:DI 1 "register_operand" "r")
410          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
411   ""
412   "SR %0,%1,%2")
414 (define_insn "lshrdi3"
415   [(set (match_operand:DI 0 "register_operand" "=r")
416         (lshiftrt:DI
417          (match_operand:DI 1 "register_operand" "r")
418          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
419   ""
420   "SRU %0,%1,%2")
422 (define_insn "negdi2"
423   [(set (match_operand:DI 0 "register_operand" "=r")
424         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
425   ""
426   "NEGU %0,0,%1")
428 (define_expand "negdf2"
429   [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
430                    (neg:DF (match_operand:DF 1 "register_operand" "r")))
431               (use (match_dup 2))])]
432   ""
434   /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0.  */
435   operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
438 (define_insn "*expanded_negdf2"
439   [(set (match_operand:DF 0 "register_operand" "=r")
440         (neg:DF (match_operand:DF 1 "register_operand" "r")))
441    (use (match_operand:DI 2 "register_operand" "r"))]
442   ""
443   "XOR %0,%1,%2")
445 ;; FIXME: define_expand for absdi2?
447 (define_insn "absdf2"
448   [(set (match_operand:DF 0 "register_operand" "=r")
449         (abs:DF (match_operand:DF 1 "register_operand" "0")))]
450   ""
451   "ANDNH %0,#8000")
453 (define_insn "sqrtdf2"
454   [(set (match_operand:DF 0 "register_operand" "=r")
455         (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
456   ""
457   "FSQRT %0,%1")
459 ;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
461 (define_insn "one_cmpldi2"
462   [(set (match_operand:DI 0 "register_operand" "=r")
463         (not:DI (match_operand:DI 1 "register_operand" "r")))]
464   ""
465   "NOR %0,%1,0")
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 "*cmpdi_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 "*cmps"
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)));
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)));
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 TARGET_SECONDARY_MEMORY_NEEDED?
651 (define_expand "truncdfsf2"
652   [(set (match_operand:SF 0 "nonimmediate_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)));
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")
688         (float_extend:DF (match_operand:SF 1 "nonimmediate_operand")))]
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)));
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_dup 4) (match_dup 5))
728    (set (match_operand:DF 0 "register_operand" "")
729         (if_then_else:DF
730          (match_operand 1 "comparison_operator" "")
731          (match_operand:DF 2 "mmix_reg_or_0_operand" "")
732          (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
733   ""
734   "
736   enum rtx_code code = GET_CODE (operands[1]);
737   if (code == LE || code == GE)
738     FAIL;
740   operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
741                                       XEXP (operands[1], 1));
742   operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
743                                  XEXP (operands[1], 0),
744                                  XEXP (operands[1], 1));
745   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
748 (define_expand "movdicc"
749   [(set (match_dup 4) (match_dup 5))
750    (set (match_operand:DI 0 "register_operand" "")
751         (if_then_else:DI
752          (match_operand 1 "comparison_operator" "")
753          (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
754          (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
755   ""
756   "
758   enum rtx_code code = GET_CODE (operands[1]);
759   if (code == LE || code == GE)
760     FAIL;
762   operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
763                                       XEXP (operands[1], 1));
764   operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
765                                  XEXP (operands[1], 0),
766                                  XEXP (operands[1], 1));
767   operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
770 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
771 (define_insn "*movdicc_real_foldable"
772   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
773         (if_then_else:DI
774          (match_operator 2 "mmix_foldable_comparison_operator"
775                          [(match_operand:DI 3 "register_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")
786 (define_insn "*movdicc_real_reversible"
787   [(set
788     (match_operand:DI 0 "register_operand"         "=r ,r ,r ,r")
789     (if_then_else:DI
790      (match_operator
791       2 "mmix_comparison_operator"
792       [(match_operand 3 "mmix_reg_cc_operand"       "r ,r ,r ,r")
793       (const_int 0)])
794      (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
795      (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
796   "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
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")
803 (define_insn "*movdicc_real_nonreversible"
804   [(set
805     (match_operand:DI 0 "register_operand"         "=r ,r")
806     (if_then_else:DI
807      (match_operator
808       2 "mmix_comparison_operator"
809       [(match_operand 3 "mmix_reg_cc_operand"       "r ,r")
810       (const_int 0)])
811      (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
812      (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
813   "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
814   "@
815    CS%d2 %0,%3,%1
816    ZS%d2 %0,%3,%1")
818 (define_insn "*movdfcc_real_foldable"
819   [(set
820     (match_operand:DF 0 "register_operand"      "=r  ,r  ,r  ,r")
821     (if_then_else:DF
822      (match_operator
823       2 "mmix_foldable_comparison_operator"
824       [(match_operand:DI 3 "register_operand"    "r  ,r  ,r  ,r")
825       (const_int 0)])
826      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
827      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
828   ""
829   "@
830    CS%d2 %0,%3,%1
831    CS%D2 %0,%3,%4
832    ZS%d2 %0,%3,%1
833    ZS%D2 %0,%3,%4")
835 (define_insn "*movdfcc_real_reversible"
836   [(set
837     (match_operand:DF 0 "register_operand"      "=r  ,r  ,r  ,r")
838     (if_then_else:DF
839      (match_operator
840       2 "mmix_comparison_operator"
841       [(match_operand 3 "mmix_reg_cc_operand"    "r  ,r  ,r  ,r")
842       (const_int 0)])
843      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
844      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
845   "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
846   "@
847    CS%d2 %0,%3,%1
848    CS%D2 %0,%3,%4
849    ZS%d2 %0,%3,%1
850    ZS%D2 %0,%3,%4")
852 (define_insn "*movdfcc_real_nonreversible"
853   [(set
854     (match_operand:DF 0 "register_operand"      "=r  ,r")
855     (if_then_else:DF
856      (match_operator
857       2 "mmix_comparison_operator"
858       [(match_operand 3 "mmix_reg_cc_operand"    "r  ,r")
859       (const_int 0)])
860      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
861      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,GM")))]
862   "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
863   "@
864    CS%d2 %0,%3,%1
865    ZS%d2 %0,%3,%1")
867 ;; FIXME: scc insns will probably help, I just skip them
868 ;; right now.  Revisit.
870 (define_expand "cbranchdi4"
871   [(set (match_dup 4)
872         (match_op_dup 5
873          [(match_operand:DI 1 "register_operand" "")
874           (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")]))
875    (set (pc)
876         (if_then_else
877               (match_operator 0 "ordered_comparison_operator"
878                [(match_dup 4)
879                 (const_int 0)])
880               (label_ref (match_operand 3 "" ""))
881               (pc)))]
882   ""
883   "
885   operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
886                                       operands[1], operands[2]);
887   operands[5] = gen_rtx_fmt_ee (COMPARE,
888                                 GET_MODE (operands[4]),
889                                 operands[1], operands[2]);
892 (define_expand "cbranchdf4"
893   [(set (match_dup 4)
894         (match_op_dup 5
895          [(match_operand:DF 1 "register_operand" "")
896           (match_operand:DF 2 "register_operand" "")]))
897    (set (pc)
898         (if_then_else
899               (match_operator 0 "float_comparison_operator"
900                [(match_dup 4)
901                 (const_int 0)])
902               (label_ref (match_operand 3 "" ""))
903               (pc)))]
904   ""
905   "
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 (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE)
910     {
911       enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT;
912       emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX,
913                                DFmode, 0, operands[3]);
914       emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX,
915                                DFmode, 0, operands[3]);
916       DONE;
917     }
919   operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
920                                       operands[1], operands[2]);
921   operands[5] = gen_rtx_fmt_ee (COMPARE,
922                                 GET_MODE (operands[4]),
923                                 operands[1], operands[2]);
927 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
928 ;; there's no RTL code for it.  Maybe revisit in future.
930 ;; FIXME: Odd/Even matchers?
931 (define_insn "*bCC_foldable"
932   [(set (pc)
933         (if_then_else
934          (match_operator 1 "mmix_foldable_comparison_operator"
935                          [(match_operand:DI 2 "register_operand" "r")
936                           (const_int 0)])
937          (label_ref (match_operand 0 "" ""))
938          (pc)))]
939   ""
940   "%+B%d1 %2,%0")
942 (define_insn "*bCC"
943   [(set (pc)
944         (if_then_else
945          (match_operator 1 "mmix_comparison_operator"
946                          [(match_operand 2 "mmix_reg_cc_operand" "r")
947                           (const_int 0)])
948          (label_ref (match_operand 0 "" ""))
949          (pc)))]
950   ""
951   "%+B%d1 %2,%0")
953 (define_insn "*bCC_inverted_foldable"
954   [(set (pc)
955         (if_then_else
956          (match_operator 1 "mmix_foldable_comparison_operator"
957                          [(match_operand:DI 2 "register_operand" "r")
958                           (const_int 0)])
959                       (pc)
960                       (label_ref (match_operand 0 "" ""))))]
961 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
962   ""
963   "%+B%D1 %2,%0")
965 (define_insn "*bCC_inverted"
966   [(set (pc)
967         (if_then_else
968          (match_operator 1 "mmix_comparison_operator"
969                          [(match_operand 2 "mmix_reg_cc_operand" "r")
970                           (const_int 0)])
971          (pc)
972          (label_ref (match_operand 0 "" ""))))]
973   "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
974   "%+B%D1 %2,%0")
976 (define_expand "call"
977   [(parallel [(call (match_operand:QI 0 "memory_operand" "") (const_int 0))
978               (clobber (match_dup 1))])
979    (set (match_dup 1) (match_dup 2))]
980   ""
981   "
983   /* The caller checks that the operand is generally valid as an
984      address, but at -O0 nothing makes sure that it's also a valid
985      call address for a *call*; a mmix_symbolic_or_address_operand.
986      Force into a register if it isn't.  */
987   if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
988                                          GET_MODE (XEXP (operands[0], 0))))
989     operands[0]
990       = replace_equiv_address (operands[0],
991                                force_reg (Pmode, XEXP (operands[0], 0)));
993   /* Note that we overwrite the generic operands[1] and operands[2]; we
994      don't use those values.  */
995   operands[1] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
997   /* Since the epilogue 'uses' the return address, and it is clobbered
998      in the call, and we set it back after every call (all but one setting
999      will be optimized away), integrity is maintained.  */
1000   operands[2]
1001     = mmix_get_hard_reg_initial_val (Pmode,
1002                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1005 (define_expand "call_value"
1006   [(parallel [(set (match_operand 0 "" "")
1007                    (call (match_operand:QI 1 "memory_operand" "")
1008                          (const_int 0)))
1009               (clobber (match_dup 2))])
1010    (set (match_dup 2) (match_dup 3))]
1011   ""
1012   "
1014   /* The caller checks that the operand is generally valid as an
1015      address, but at -O0 nothing makes sure that it's also a valid
1016      call address for a *call*; a mmix_symbolic_or_address_operand.
1017      Force into a register if it isn't.  */
1018   if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
1019                                          GET_MODE (XEXP (operands[1], 0))))
1020     operands[1]
1021       = replace_equiv_address (operands[1],
1022                                force_reg (Pmode, XEXP (operands[1], 0)));
1024   /* Note that we overwrite the generic operands[2] and operands[3]; we
1025      don't use those values.  */
1026   operands[2] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1028   /* Since the epilogue 'uses' the return address, and it is clobbered
1029      in the call, and we set it back after every call (all but one setting
1030      will be optimized away), integrity is maintained.  */
1031   operands[3]
1032     = mmix_get_hard_reg_initial_val (Pmode,
1033                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1036 ;; Don't use 'p' here.  A 'p' must stand first in constraints, or reload
1037 ;; messes up, not registering the address for reload.  Several C++
1038 ;; testcases, including g++.brendan/crash40.C.  FIXME: This is arguably a
1039 ;; bug in gcc.  Note line ~2612 in reload.c, that does things on the
1040 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1041 ;; ~3017 that says:
1042 ;; <<   case 'p':
1043 ;;           /* All necessary reloads for an address_operand
1044 ;;              were handled in find_reloads_address.  */>>
1045 ;; Sorry, I have not dug deeper.  If symbolic addresses are used
1046 ;; rarely compared to addresses in registers, disparaging the
1047 ;; first ("p") alternative by adding ? in the first operand
1048 ;; might do the trick.  We define 'U' as a synonym to 'p', but without the
1049 ;; caveats (and very small advantages) of 'p'.
1050 ;; As of r190682 still so: newlib/libc/stdlib/dtoa.c ICEs if "p" is used.
1051 (define_insn "*call_real"
1052   [(call (mem:QI
1053           (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1054          (const_int 0))
1055    (clobber (reg:DI MMIX_rJ_REGNUM))]
1056   ""
1057   "@
1058    PUSHJ $%!,%0
1059    PUSHGO $%!,%a0")
1061 (define_insn "*call_value_real"
1062   [(set (match_operand 0 "register_operand" "=r,r")
1063         (call (mem:QI
1064                (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1065               (const_int 0)))
1066    (clobber (reg:DI MMIX_rJ_REGNUM))]
1067   ""
1068   "@
1069    PUSHJ $%!,%1
1070    PUSHGO $%!,%a1")
1072 ;; I hope untyped_call and untyped_return are not needed for MMIX.
1073 ;; Users of Objective-C will notice.
1075 ; Generated by GCC.
1076 (define_expand "return"
1077   [(return)]
1078   "mmix_use_simple_return ()"
1079   "")
1081 ; Generated by the epilogue expander.
1082 (define_insn "*expanded_return"
1083   [(return)]
1084   ""
1085   "POP %.,0")
1087 (define_expand "prologue"
1088   [(const_int 0)]
1089   ""
1090   "mmix_expand_prologue (); DONE;")
1092 ; Note that the (return) from the expander itself is always the last insn
1093 ; in the epilogue.
1094 (define_expand "epilogue"
1095   [(return)]
1096   ""
1097   "mmix_expand_epilogue ();")
1099 (define_insn "nop"
1100   [(const_int 0)]
1101   ""
1102   "SWYM 0,0,0")
1104 (define_insn "jump"
1105   [(set (pc) (label_ref (match_operand 0 "" "")))]
1106   ""
1107   "JMP %0")
1109 (define_insn "indirect_jump"
1110   [(set (pc) (match_operand 0 "address_operand" "p"))]
1111   ""
1112   "GO $255,%a0")
1114 ;; FIXME: This is just a jump, and should be expanded to one.
1115 (define_insn "tablejump"
1116   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1117    (use (label_ref (match_operand 1 "" "")))]
1118   ""
1119   "GO $255,%a0")
1121 ;; The only peculiar thing is that the register stack has to be unwound at
1122 ;; nonlocal_goto_receiver.  At each function that has a nonlocal label, we
1123 ;; save at function entry the location of the "alpha" register stack
1124 ;; pointer, rO, in a stack slot known to that function (right below where
1125 ;; the frame-pointer would be located).
1126 ;; In the nonlocal goto receiver, we unwind the register stack by a series
1127 ;; of "pop 0,0" until rO equals the saved value.  (If it goes lower, we
1128 ;; should die with a trap.)
1129 (define_expand "nonlocal_goto_receiver"
1130   [(parallel [(unspec_volatile [(match_dup 1)] 1)
1131               (clobber (scratch:DI))
1132               (clobber (reg:DI MMIX_rJ_REGNUM))])
1133    (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
1134   ""
1135   "
1137   operands[0]
1138     = mmix_get_hard_reg_initial_val (Pmode,
1139                                      MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1141   /* We need the frame-pointer to be live or the equivalent
1142      expression, so refer to it in the pattern.  We can't use a MEM
1143      (that may contain out-of-range offsets in the final expression)
1144      for fear that middle-end will legitimize it or replace the address
1145      using temporary registers (which are not revived at this point).  */
1146   operands[1] = frame_pointer_rtx;
1148   /* Mark this function as containing a landing-pad.  */
1149   cfun->machine->has_landing_pad = 1;
1152 ;; GCC can insist on using saved registers to keep the slot address in
1153 ;; "across" the exception, or (perhaps) to use saved registers in the
1154 ;; address and re-use them after the register stack unwind, so it's best
1155 ;; to form the address ourselves.
1156 (define_insn "*nonlocal_goto_receiver_expanded"
1157   [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1)
1158    (clobber (match_scratch:DI 0 "=&r"))
1159    (clobber (reg:DI MMIX_rJ_REGNUM))]
1160   ""
1162   rtx my_operands[3];
1163   const char *my_template
1164     = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
1165 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1167   my_operands[1] = operands[0];
1168   my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET);
1170   if (operands[1] == hard_frame_pointer_rtx)
1171     {
1172       mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
1173                                     MMIX_fp_rO_OFFSET, 1);
1174       my_operands[0]
1175         = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]);
1176     }
1177   else
1178     {
1179       int64_t offs = INTVAL (XEXP (operands[1], 1));
1180       offs += MMIX_fp_rO_OFFSET;
1182       if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I))
1183         my_operands[0]
1184           = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1185       else
1186         {
1187           mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
1188                                         offs, 1);
1189           my_operands[0]
1190             = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]);
1191         }
1192     }
1194   output_asm_insn (my_template, my_operands);
1195   return "";
1198 (define_insn "*Naddu"
1199   [(set (match_operand:DI 0 "register_operand" "=r")
1200         (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1201                           (match_operand:DI 2 "const_int_operand" "n"))
1202                  (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
1203   "GET_CODE (operands[2]) == CONST_INT
1204    && (INTVAL (operands[2]) == 2
1205        || INTVAL (operands[2]) == 4
1206        || INTVAL (operands[2]) == 8
1207        || INTVAL (operands[2]) == 16)"
1208   "%2ADDU %0,%1,%3")
1210 (define_insn "*andn"
1211   [(set (match_operand:DI 0 "register_operand" "=r")
1212         (and:DI
1213          (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1214          (match_operand:DI 2 "register_operand" "r")))]
1215   ""
1216   "ANDN %0,%2,%1")
1218 (define_insn "*nand"
1219   [(set (match_operand:DI 0 "register_operand" "=r")
1220         (ior:DI
1221          (not:DI (match_operand:DI 1 "register_operand" "%r"))
1222          (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1223   ""
1224   "NAND %0,%1,%2")
1226 (define_insn "*nor"
1227   [(set (match_operand:DI 0 "register_operand" "=r")
1228         (and:DI
1229          (not:DI (match_operand:DI 1 "register_operand" "%r"))
1230          (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1231   ""
1232   "NOR %0,%1,%2")
1234 (define_insn "*nxor"
1235   [(set (match_operand:DI 0 "register_operand" "=r")
1236         (not:DI
1237          (xor:DI (match_operand:DI 1 "register_operand" "%r")
1238                  (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1239   ""
1240   "NXOR %0,%1,%2")
1242 (define_insn "sync_icache"
1243   [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1244                      (match_operand:DI 1 "const_int_operand" "I")] 0)]
1245   ""
1246   "SYNCID %1,%0")
1248 ;; Local Variables:
1249 ;; mode: lisp
1250 ;; indent-tabs-mode: t
1251 ;; End: