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)
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:
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.
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
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"))]
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"))]
77 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
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"))]
92 ;; We assume all "s" are addresses. Does that hold?
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"))]
110 ;; Note that we move around the float as a collection of bits; no
111 ;; conversion to double.
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"))]
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"))]
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"
157 (define_expand "movcc"
158 [(set (match_operand:CC 0 "nonimmediate_operand" "")
159 (match_operand:CC 1 "nonimmediate_operand" ""))]
163 (define_expand "movcc_uns"
164 [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
165 (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
169 (define_expand "movcc_fp"
170 [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
171 (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
175 (define_expand "movcc_fpeq"
176 [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
177 (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
181 (define_expand "movcc_fun"
182 [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
183 (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
187 (define_insn "adddi3"
188 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
190 (match_operand:DI 1 "register_operand" "%r,r,0")
191 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
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")))]
205 ;; Insn canonicalization *should* have removed the need for an integer
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")))]
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")))]
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"))]
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")))]
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")))]
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")))]
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")
267 (match_operand:DI 1 "register_operand" "%r,0")
268 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
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")))]
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")))]
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"
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)))]
322 (define_expand "divdi3"
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"
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"
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"
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"
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"
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")
377 (match_operand:DI 1 "register_operand" "r")
378 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
382 (define_insn "ashrdi3"
383 [(set (match_operand:DI 0 "register_operand" "=r")
385 (match_operand:DI 1 "register_operand" "r")
386 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
390 (define_insn "lshrdi3"
391 [(set (match_operand:DI 0 "register_operand" "=r")
393 (match_operand:DI 1 "register_operand" "r")
394 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
398 (define_insn "negdi2"
399 [(set (match_operand:DI 0 "register_operand" "=r")
400 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
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))])]
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"))]
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")))]
429 (define_insn "sqrtdf2"
430 [(set (match_operand:DF 0 "register_operand" "=r")
431 (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
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")))]
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" "")]
451 mmix_compare_op0 = operands[0];
452 mmix_compare_op1 = operands[1];
456 (define_expand "cmpdf"
457 [(match_operand:DF 0 "register_operand" "")
458 (match_operand:DF 1 "register_operand" "")]
462 mmix_compare_op0 = operands[0];
463 mmix_compare_op1 = operands[1];
467 ;; When the user-patterns expand, the resulting insns will match the
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
477 (define_insn "*cmpcc_folded"
478 [(set (match_operand:CC 0 "register_operand" "=r")
480 (match_operand:DI 1 "register_operand" "r")
482 ;; FIXME: Can we test equivalence any other way?
483 ;; FIXME: Can we fold any other way?
484 "REGNO (operands[1]) == REGNO (operands[0])"
485 "%% folded: cmp %0,%1,0")
487 (define_insn "*cmpcc"
488 [(set (match_operand:CC 0 "register_operand" "=r")
490 (match_operand:DI 1 "register_operand" "r")
491 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
496 [(set (match_operand:CC_UNS 0 "register_operand" "=r")
498 (match_operand:DI 1 "register_operand" "r")
499 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
504 [(set (match_operand:CC_FP 0 "register_operand" "=r")
506 (match_operand:DF 1 "register_operand" "r")
507 (match_operand:DF 2 "register_operand" "r")))]
511 ;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to
512 ;; make signalling compliant.
514 [(set (match_operand:CC_FPEQ 0 "register_operand" "=r")
516 (match_operand:DF 1 "register_operand" "r")
517 (match_operand:DF 2 "register_operand" "r")))]
522 [(set (match_operand:CC_FUN 0 "register_operand" "=r")
524 (match_operand:DF 1 "register_operand" "r")
525 (match_operand:DF 2 "register_operand" "r")))]
529 ;; In order to get correct rounding, we have to use SFLOT and SFLOTU for
530 ;; conversion. They do not convert to SFmode; they convert to DFmode,
531 ;; with rounding as of SFmode. They are not usable as is, but we pretend
532 ;; we have a single instruction but emit two.
534 ;; Note that this will (somewhat unexpectedly) create an inexact
535 ;; exception if rounding is necessary - has to be masked off in crt0?
536 (define_expand "floatdisf2"
537 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
539 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
540 ;; Let's use a DI scratch, since SF don't generally get into
541 ;; registers. Dunno what's best; it's really a DF, but that
542 ;; doesn't logically follow from operands in the pattern.
543 (clobber (match_scratch:DI 2 "=&r"))])]
547 if (GET_CODE (operands[0]) != MEM)
551 /* FIXME: This stack-slot remains even at -O3. There must be a
554 = validize_mem (assign_stack_temp (SFmode,
555 GET_MODE_SIZE (SFmode), 0));
556 emit_insn (gen_floatdisf2 (stack_slot, operands[1]));
557 emit_move_insn (operands[0], stack_slot);
562 (define_insn "*floatdisf2_real"
563 [(set (match_operand:SF 0 "memory_operand" "=m")
565 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
566 (clobber (match_scratch:DI 2 "=&r"))]
568 "SFLOT %2,%1\;STSF %2,%0")
570 (define_expand "floatunsdisf2"
571 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
573 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
574 ;; Let's use a DI scratch, since SF don't generally get into
575 ;; registers. Dunno what's best; it's really a DF, but that
576 ;; doesn't logically follow from operands in the pattern.
577 (clobber (scratch:DI))])]
581 if (GET_CODE (operands[0]) != MEM)
585 /* FIXME: This stack-slot remains even at -O3. Must be a better
588 = validize_mem (assign_stack_temp (SFmode,
589 GET_MODE_SIZE (SFmode), 0));
590 emit_insn (gen_floatunsdisf2 (stack_slot, operands[1]));
591 emit_move_insn (operands[0], stack_slot);
596 (define_insn "*floatunsdisf2_real"
597 [(set (match_operand:SF 0 "memory_operand" "=m")
599 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
600 (clobber (match_scratch:DI 2 "=&r"))]
602 "SFLOTU %2,%1\;STSF %2,%0")
604 ;; Note that this will (somewhat unexpectedly) create an inexact
605 ;; exception if rounding is necessary - has to be masked off in crt0?
606 (define_insn "floatdidf2"
607 [(set (match_operand:DF 0 "register_operand" "=r")
609 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
613 (define_insn "floatunsdidf2"
614 [(set (match_operand:DF 0 "register_operand" "=r")
616 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
620 (define_insn "ftruncdf2"
621 [(set (match_operand:DF 0 "register_operand" "=r")
622 (fix:DF (match_operand:DF 1 "register_operand" "r")))]
627 ;; Note that this will (somewhat unexpectedly) create an inexact
628 ;; exception if rounding is necessary - has to be masked off in crt0?
629 (define_insn "fix_truncdfdi2"
630 [(set (match_operand:DI 0 "register_operand" "=r")
631 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
636 (define_insn "fixuns_truncdfdi2"
637 [(set (match_operand:DI 0 "register_operand" "=r")
639 (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
644 ;; It doesn't seem like it's possible to have memory_operand as a
645 ;; predicate here (testcase: libgcc2 floathisf). FIXME: Shouldn't it be
646 ;; possible to do that? Bug in GCC? Anyway, this used to be a simple
647 ;; pattern with a memory_operand predicate, but was split up with a
648 ;; define_expand with the old pattern as "anonymous".
649 ;; FIXME: Perhaps with SECONDARY_MEMORY_NEEDED?
650 (define_expand "truncdfsf2"
651 [(set (match_operand:SF 0 "memory_operand" "")
652 (float_truncate:SF (match_operand:DF 1 "register_operand" "")))]
656 if (GET_CODE (operands[0]) != MEM)
658 /* FIXME: There should be a way to say: 'put this in operands[0]
659 but *after* the expanded insn'. */
662 /* There is no sane destination but a register here, if it wasn't
663 already MEM. (It's too hard to get fatal_insn to work here.) */
664 if (! REG_P (operands[0]))
665 internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\");
667 /* FIXME: This stack-slot remains even at -O3. Must be a better
670 = validize_mem (assign_stack_temp (SFmode,
671 GET_MODE_SIZE (SFmode), 0));
672 emit_insn (gen_truncdfsf2 (stack_slot, operands[1]));
673 emit_move_insn (operands[0], stack_slot);
678 (define_insn "*truncdfsf2_real"
679 [(set (match_operand:SF 0 "memory_operand" "=m")
680 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
684 ;; Same comment as for truncdfsf2.
685 (define_expand "extendsfdf2"
686 [(set (match_operand:DF 0 "register_operand" "=r")
687 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
691 if (GET_CODE (operands[1]) != MEM)
695 /* There is no sane destination but a register here, if it wasn't
696 already MEM. (It's too hard to get fatal_insn to work here.) */
697 if (! REG_P (operands[0]))
698 internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\");
700 /* FIXME: This stack-slot remains even at -O3. There must be a
703 = validize_mem (assign_stack_temp (SFmode,
704 GET_MODE_SIZE (SFmode), 0));
705 emit_move_insn (stack_slot, operands[1]);
706 emit_insn (gen_extendsfdf2 (operands[0], stack_slot));
711 (define_insn "*extendsfdf2_real"
712 [(set (match_operand:DF 0 "register_operand" "=r")
713 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
717 ;; Neither sign-extend nor zero-extend are necessary; gcc knows how to
718 ;; synthesize using shifts or and, except with a memory source and not
719 ;; completely optimal. FIXME: Actually, other bugs surface when those
720 ;; patterns are defined; fix later.
722 ;; There are no sane values with the bit-patterns of (int) 0..255 except
723 ;; 0 to use in movdfcc.
725 (define_expand "movdfcc"
726 [(set (match_operand:DF 0 "register_operand" "")
728 (match_operand 1 "comparison_operator" "")
729 (match_operand:DF 2 "mmix_reg_or_0_operand" "")
730 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
734 enum rtx_code code = GET_CODE (operands[1]);
735 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
737 if (cc_reg == NULL_RTX)
739 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
742 (define_expand "movdicc"
743 [(set (match_operand:DI 0 "register_operand" "")
745 (match_operand 1 "comparison_operator" "")
746 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
747 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
751 enum rtx_code code = GET_CODE (operands[1]);
752 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
754 if (cc_reg == NULL_RTX)
756 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
759 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
760 (define_insn "*movdicc_real_foldable"
761 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
763 (match_operator 2 "mmix_foldable_comparison_operator"
764 [(match_operand:DI 3 "register_operand" "r,r,r,r")
766 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
767 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
775 (define_insn "*movdicc_real_reversible"
777 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r")
780 2 "mmix_comparison_operator"
781 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
783 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
784 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
785 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
792 (define_insn "*movdicc_real_nonreversible"
794 (match_operand:DI 0 "register_operand" "=r ,r")
797 2 "mmix_comparison_operator"
798 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
800 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
801 (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
802 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
807 (define_insn "*movdfcc_real_foldable"
809 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
812 2 "mmix_foldable_comparison_operator"
813 [(match_operand:DI 3 "register_operand" "r ,r ,r ,r")
815 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
816 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
824 (define_insn "*movdfcc_real_reversible"
826 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
829 2 "mmix_comparison_operator"
830 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
832 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
833 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
834 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
841 (define_insn "*movdfcc_real_nonreversible"
843 (match_operand:DF 0 "register_operand" "=r ,r")
846 2 "mmix_comparison_operator"
847 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
849 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
850 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,GM")))]
851 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
856 ;; FIXME: scc patterns will probably help, I just skip them
857 ;; right now. Revisit.
861 (if_then_else (eq (match_dup 1) (const_int 0))
862 (label_ref (match_operand 0 "" ""))
868 = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1);
873 (if_then_else (ne (match_dup 1) (const_int 0))
874 (label_ref (match_operand 0 "" ""))
880 = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1);
885 (if_then_else (gt (match_dup 1) (const_int 0))
886 (label_ref (match_operand 0 "" ""))
892 = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1);
897 (if_then_else (le (match_dup 1) (const_int 0))
898 (label_ref (match_operand 0 "" ""))
904 = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
906 /* The head comment of optabs.c:can_compare_p says we're required to
907 implement this, so we have to clean up the mess here. */
908 if (operands[1] == NULL_RTX)
910 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
911 emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0]));
912 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
919 (if_then_else (ge (match_dup 1) (const_int 0))
920 (label_ref (match_operand 0 "" ""))
926 = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
928 /* The head comment of optabs.c:can_compare_p says we're required to
929 implement this, so we have to clean up the mess here. */
930 if (operands[1] == NULL_RTX)
932 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
933 emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0]));
934 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
941 (if_then_else (lt (match_dup 1) (const_int 0))
942 (label_ref (match_operand 0 "" ""))
948 = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);
951 (define_expand "bgtu"
953 (if_then_else (gtu (match_dup 1) (const_int 0))
954 (label_ref (match_operand 0 "" ""))
960 = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);
963 (define_expand "bleu"
965 (if_then_else (leu (match_dup 1) (const_int 0))
966 (label_ref (match_operand 0 "" ""))
972 = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);
975 (define_expand "bgeu"
977 (if_then_else (geu (match_dup 1) (const_int 0))
978 (label_ref (match_operand 0 "" ""))
984 = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);
987 (define_expand "bltu"
989 (if_then_else (ltu (match_dup 1) (const_int 0))
990 (label_ref (match_operand 0 "" ""))
996 = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);
999 (define_expand "bunordered"
1001 (if_then_else (unordered (match_dup 1) (const_int 0))
1002 (label_ref (match_operand 0 "" ""))
1008 = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1);
1010 if (operands[1] == NULL_RTX)
1014 (define_expand "bordered"
1016 (if_then_else (ordered (match_dup 1) (const_int 0))
1017 (label_ref (match_operand 0 "" ""))
1023 = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);
1026 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
1027 ;; there's no RTL code for it. Maybe revisit in future.
1029 ;; FIXME: Odd/Even matchers?
1030 (define_insn "*bCC_foldable"
1033 (match_operator 1 "mmix_foldable_comparison_operator"
1034 [(match_operand:DI 2 "register_operand" "r")
1036 (label_ref (match_operand 0 "" ""))
1044 (match_operator 1 "mmix_comparison_operator"
1045 [(match_operand 2 "mmix_reg_cc_operand" "r")
1047 (label_ref (match_operand 0 "" ""))
1052 (define_insn "*bCC_inverted_foldable"
1055 (match_operator 1 "mmix_foldable_comparison_operator"
1056 [(match_operand:DI 2 "register_operand" "r")
1059 (label_ref (match_operand 0 "" ""))))]
1060 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
1064 (define_insn "*bCC_inverted"
1067 (match_operator 1 "mmix_comparison_operator"
1068 [(match_operand 2 "mmix_reg_cc_operand" "r")
1071 (label_ref (match_operand 0 "" ""))))]
1072 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
1075 (define_expand "call"
1076 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
1077 (match_operand 1 "general_operand" ""))
1078 (use (match_operand 2 "general_operand" ""))
1079 (clobber (match_dup 4))])
1080 (set (match_dup 4) (match_dup 3))]
1084 /* The caller checks that the operand is generally valid as an
1085 address, but at -O0 nothing makes sure that it's also a valid
1086 call address for a *call*; a mmix_symbolic_or_address_operand.
1087 Force into a register if it isn't. */
1088 if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
1089 GET_MODE (XEXP (operands[0], 0))))
1091 = replace_equiv_address (operands[0],
1092 force_reg (Pmode, XEXP (operands[0], 0)));
1094 /* Since the epilogue 'uses' the return address, and it is clobbered
1095 in the call, and we set it back after every call (all but one setting
1096 will be optimized away), integrity is maintained. */
1098 = mmix_get_hard_reg_initial_val (Pmode,
1099 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1101 /* FIXME: There's a bug in gcc which causes NULL to be passed as
1102 operand[2] when we get out of registers, which later confuses gcc.
1103 Work around it by replacing it with const_int 0. Possibly documentation
1105 if (operands[2] == NULL_RTX)
1106 operands[2] = const0_rtx;
1108 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1111 (define_expand "call_value"
1112 [(parallel [(set (match_operand 0 "" "")
1113 (call (match_operand:QI 1 "memory_operand" "")
1114 (match_operand 2 "general_operand" "")))
1115 (use (match_operand 3 "general_operand" ""))
1116 (clobber (match_dup 5))])
1117 (set (match_dup 5) (match_dup 4))]
1121 /* The caller checks that the operand is generally valid as an
1122 address, but at -O0 nothing makes sure that it's also a valid
1123 call address for a *call*; a mmix_symbolic_or_address_operand.
1124 Force into a register if it isn't. */
1125 if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
1126 GET_MODE (XEXP (operands[1], 0))))
1128 = replace_equiv_address (operands[1],
1129 force_reg (Pmode, XEXP (operands[1], 0)));
1131 /* Since the epilogue 'uses' the return address, and it is clobbered
1132 in the call, and we set it back after every call (all but one setting
1133 will be optimized away), integrity is maintained. */
1135 = mmix_get_hard_reg_initial_val (Pmode,
1136 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1138 /* FIXME: See 'call'. */
1139 if (operands[3] == NULL_RTX)
1140 operands[3] = const0_rtx;
1142 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
1143 *next* argument register, not the number of arguments in registers.
1144 (There used to be code here where that mattered.) */
1146 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1149 ;; Don't use 'p' here. A 'p' must stand first in constraints, or reload
1150 ;; messes up, not registering the address for reload. Several C++
1151 ;; testcases, including g++.brendan/crash40.C. FIXME: This is arguably a
1152 ;; bug in gcc. Note line ~2612 in reload.c, that does things on the
1153 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1156 ;; /* All necessary reloads for an address_operand
1157 ;; were handled in find_reloads_address. */>>
1158 ;; Sorry, I have not dug deeper. If symbolic addresses are used
1159 ;; rarely compared to addresses in registers, disparaging the
1160 ;; first ("p") alternative by adding ? in the first operand
1161 ;; might do the trick. We define 'U' as a synonym to 'p', but without the
1162 ;; caveats (and very small advantages) of 'p'.
1163 (define_insn "*call_real"
1165 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1166 (match_operand 1 "" ""))
1167 (use (match_operand 2 "" ""))
1168 (clobber (reg:DI MMIX_rJ_REGNUM))]
1174 (define_insn "*call_value_real"
1175 [(set (match_operand 0 "register_operand" "=r,r")
1177 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1178 (match_operand 2 "" "")))
1179 (use (match_operand 3 "" ""))
1180 (clobber (reg:DI MMIX_rJ_REGNUM))]
1186 ;; I hope untyped_call and untyped_return are not needed for MMIX.
1187 ;; Users of Objective-C will notice.
1190 (define_expand "return"
1192 "mmix_use_simple_return ()"
1195 ; Generated by the epilogue expander.
1196 (define_insn "*expanded_return"
1201 (define_expand "prologue"
1204 "mmix_expand_prologue (); DONE;")
1206 ; Note that the (return) from the expander itself is always the last insn
1208 (define_expand "epilogue"
1211 "mmix_expand_epilogue ();")
1219 [(set (pc) (label_ref (match_operand 0 "" "")))]
1223 (define_insn "indirect_jump"
1224 [(set (pc) (match_operand 0 "address_operand" "p"))]
1228 ;; FIXME: This is just a jump, and should be expanded to one.
1229 (define_insn "tablejump"
1230 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1231 (use (label_ref (match_operand 1 "" "")))]
1235 ;; The only peculiar thing is that the register stack has to be unwound at
1236 ;; nonlocal_goto_receiver. At each function that has a nonlocal label, we
1237 ;; save at function entry the location of the "alpha" register stack
1238 ;; pointer, rO, in a stack slot known to that function (right below where
1239 ;; the frame-pointer would be located).
1240 ;; In the nonlocal goto receiver, we unwind the register stack by a series
1241 ;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
1242 ;; should die with a trap.)
1243 (define_expand "nonlocal_goto_receiver"
1244 [(parallel [(unspec_volatile [(const_int 0)] 1)
1245 (clobber (scratch:DI))
1246 (clobber (reg:DI MMIX_rJ_REGNUM))])
1247 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
1252 = mmix_get_hard_reg_initial_val (Pmode,
1253 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1255 /* Mark this function as containing a landing-pad. */
1256 cfun->machine->has_landing_pad = 1;
1259 ;; GCC can insist on using saved registers to keep the slot address in
1260 ;; "across" the exception, or (perhaps) to use saved registers in the
1261 ;; address and re-use them after the register stack unwind, so it's best
1262 ;; to form the address ourselves.
1263 (define_insn "*nonlocal_goto_receiver_expanded"
1264 [(unspec_volatile [(const_int 0)] 1)
1265 (clobber (match_scratch:DI 0 "=&r"))
1266 (clobber (reg:DI MMIX_rJ_REGNUM))]
1269 rtx temp_reg = operands[0];
1271 HOST_WIDEST_INT offs;
1272 const char *my_template
1273 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
1274 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1276 my_operands[1] = temp_reg;
1278 /* If we have a frame-pointer (hence unknown stack-pointer offset),
1279 just use the frame-pointer and the known offset. */
1280 if (frame_pointer_needed)
1282 my_operands[0] = GEN_INT (-MMIX_fp_rO_OFFSET);
1284 output_asm_insn ("NEGU %1,0,%0", my_operands);
1285 my_operands[0] = gen_rtx_PLUS (Pmode, frame_pointer_rtx, temp_reg);
1289 /* We know the fp-based offset, so "eliminate" it to be sp-based. */
1291 = (mmix_initial_elimination_offset (MMIX_FRAME_POINTER_REGNUM,
1292 MMIX_STACK_POINTER_REGNUM)
1293 + MMIX_fp_rO_OFFSET);
1295 if (offs >= 0 && offs <= 255)
1297 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1300 mmix_output_register_setting (asm_out_file, REGNO (temp_reg),
1302 my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, temp_reg);
1306 output_asm_insn (my_template, my_operands);
1310 (define_insn "*Naddu"
1311 [(set (match_operand:DI 0 "register_operand" "=r")
1312 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1313 (match_operand:DI 2 "const_int_operand" "n"))
1314 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
1315 "GET_CODE (operands[2]) == CONST_INT
1316 && (INTVAL (operands[2]) == 2
1317 || INTVAL (operands[2]) == 4
1318 || INTVAL (operands[2]) == 8
1319 || INTVAL (operands[2]) == 16)"
1322 (define_insn "*andn"
1323 [(set (match_operand:DI 0 "register_operand" "=r")
1325 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1326 (match_operand:DI 2 "register_operand" "r")))]
1330 (define_insn "*nand"
1331 [(set (match_operand:DI 0 "register_operand" "=r")
1333 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1334 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1339 [(set (match_operand:DI 0 "register_operand" "=r")
1341 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1342 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1346 (define_insn "*nxor"
1347 [(set (match_operand:DI 0 "register_operand" "=r")
1349 (xor:DI (match_operand:DI 1 "register_operand" "%r")
1350 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1354 (define_insn "sync_icache"
1355 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1356 (match_operand:DI 1 "const_int_operand" "I")] 0)]
1362 ;; indent-tabs-mode: t