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