1 ;; GCC machine description for MMIX
2 ;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
5 ;; This file is part of GNU CC.
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GNU CC 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 GNU CC; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
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.
38 ;; - Use new formats; e.g. '{' not '"*{'.
41 [(MMIX_rJ_REGNUM 259)]
44 ;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they
47 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
48 (match_operand:QI 1 "general_operand" "r,LS,K,rI,x,m,r,n"))]
61 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
62 (match_operand:HI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
74 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
76 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
77 (match_operand:SI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
89 ;; We assume all "s" are addresses. Does that hold?
91 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
92 (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))]
107 ;; Note that we move around the float as a collection of bits; no
108 ;; conversion to double.
110 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
111 (match_operand:SF 1 "general_operand" "r,G,r,x,m,r,F"))]
123 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
124 (match_operand:DF 1 "general_operand" "r,G,r,x,m,r,F"))]
135 (define_insn "adddi3"
136 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
138 (match_operand:DI 1 "register_operand" "%r,r,0")
139 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
146 (define_insn "adddf3"
147 [(set (match_operand:DF 0 "register_operand" "=r")
148 (plus:DF (match_operand:DF 1 "register_operand" "%r")
149 (match_operand:DF 2 "register_operand" "r")))]
153 ;; Insn canonicalization *should* have removed the need for an integer
155 (define_insn "subdi3"
156 [(set (match_operand:DI 0 "register_operand" "=r,r")
157 (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
158 (match_operand:DI 2 "register_operand" "r,r")))]
164 (define_insn "subdf3"
165 [(set (match_operand:DF 0 "register_operand" "=r")
166 (minus:DF (match_operand:DF 1 "register_operand" "r")
167 (match_operand:DF 2 "register_operand" "r")))]
171 ;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
172 ;; %{something}2ADDU %0,%1,0)? Hopefully GCC should still handle it, so
173 ;; we don't have to taint the machine description. If results are bad
174 ;; enough, we may have to do it anyway.
175 (define_insn "muldi3"
176 [(set (match_operand:DI 0 "register_operand" "=r,r")
177 (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
178 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
179 (clobber (match_scratch:DI 3 "=X,z"))]
185 (define_insn "muldf3"
186 [(set (match_operand:DF 0 "register_operand" "=r")
187 (mult:DF (match_operand:DF 1 "register_operand" "r")
188 (match_operand:DF 2 "register_operand" "r")))]
192 (define_insn "divdf3"
193 [(set (match_operand:DF 0 "register_operand" "=r")
194 (div:DF (match_operand:DF 1 "register_operand" "r")
195 (match_operand:DF 2 "register_operand" "r")))]
199 ;; FIXME: Is "frem" doing the right operation for moddf3?
200 (define_insn "moddf3"
201 [(set (match_operand:DF 0 "register_operand" "=r")
202 (mod:DF (match_operand:DF 1 "register_operand" "r")
203 (match_operand:DF 2 "register_operand" "r")))]
207 ;; FIXME: Should we define_expand for smin, smax, umin, umax using a
208 ;; nifty conditional sequence?
210 ;; FIXME: The cuter andn combinations don't get here, presumably because
211 ;; they ended up in the constant pool. Check: still?
212 (define_insn "anddi3"
213 [(set (match_operand:DI 0 "register_operand" "=r,r")
215 (match_operand:DI 1 "register_operand" "%r,0")
216 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
222 (define_insn "iordi3"
223 [(set (match_operand:DI 0 "register_operand" "=r,r")
224 (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
225 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rH,LS")))]
231 (define_insn "xordi3"
232 [(set (match_operand:DI 0 "register_operand" "=r")
233 (xor:DI (match_operand:DI 1 "register_operand" "%r")
234 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
238 ;; FIXME: When TImode works for other reasons (like cross-compiling from
239 ;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
241 ;; FIXME: Check what's really reasonable for the mod part.
243 ;; One day we might persuade GCC to expand divisions with constants the
244 ;; way MMIX does; giving the remainder the sign of the divisor. But even
245 ;; then, it might be good to have an option to divide the way "everybody
246 ;; else" does. Perhaps then, this option can be on by default. Until
247 ;; then, we do division and modulus in a library function.
249 (define_insn "divmoddi4"
250 [(set (match_operand:DI 0 "register_operand" "=r")
251 (div:DI (match_operand:DI 1 "register_operand" "r")
252 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
253 (set (match_operand:DI 3 "register_operand" "=y")
254 (mod:DI (match_dup 1) (match_dup 2)))]
255 ;; Do the library stuff later.
256 "TARGET_KNUTH_DIVISION"
259 (define_insn "udivmoddi4"
260 [(set (match_operand:DI 0 "register_operand" "=r")
261 (udiv:DI (match_operand:DI 1 "register_operand" "r")
262 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
263 (set (match_operand:DI 3 "register_operand" "=y")
264 (umod:DI (match_dup 1) (match_dup 2)))]
268 (define_expand "divdi3"
270 [(set (match_operand:DI 0 "register_operand" "=&r")
271 (div:DI (match_operand:DI 1 "register_operand" "r")
272 (match_operand:DI 2 "register_operand" "r")))
273 (clobber (scratch:DI))
274 (clobber (scratch:DI))])]
275 "! TARGET_KNUTH_DIVISION"
278 ;; The %2-is-%1-case is there just to make sure things don't fail. Could
279 ;; presumably happen with optimizations off; no evidence.
280 (define_insn "*divdi3_nonknuth"
281 [(set (match_operand:DI 0 "register_operand" "=&r,r")
282 (div:DI (match_operand:DI 1 "register_operand" "r,r")
283 (match_operand:DI 2 "register_operand" "1,r")))
284 (clobber (match_scratch:DI 3 "=1,1"))
285 (clobber (match_scratch:DI 4 "=2,2"))]
286 "! TARGET_KNUTH_DIVISION"
289 XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
290 DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
292 (define_expand "moddi3"
294 [(set (match_operand:DI 0 "register_operand" "=&r")
295 (mod:DI (match_operand:DI 1 "register_operand" "r")
296 (match_operand:DI 2 "register_operand" "r")))
297 (clobber (scratch:DI))
298 (clobber (scratch:DI))])]
299 "! TARGET_KNUTH_DIVISION"
302 ;; The %2-is-%1-case is there just to make sure things don't fail. Could
303 ;; presumably happen with optimizations off; no evidence.
304 (define_insn "*moddi3_nonknuth"
305 [(set (match_operand:DI 0 "register_operand" "=&r,r")
306 (mod:DI (match_operand:DI 1 "register_operand" "r,r")
307 (match_operand:DI 2 "register_operand" "1,r")))
308 (clobber (match_scratch:DI 3 "=1,1"))
309 (clobber (match_scratch:DI 4 "=2,2"))]
310 "! TARGET_KNUTH_DIVISION"
313 NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
314 DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
316 (define_insn "ashldi3"
317 [(set (match_operand:DI 0 "register_operand" "=r")
319 (match_operand:DI 1 "register_operand" "r")
320 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
324 (define_insn "ashrdi3"
325 [(set (match_operand:DI 0 "register_operand" "=r")
327 (match_operand:DI 1 "register_operand" "r")
328 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
332 (define_insn "lshrdi3"
333 [(set (match_operand:DI 0 "register_operand" "=r")
335 (match_operand:DI 1 "register_operand" "r")
336 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
340 (define_insn "negdi2"
341 [(set (match_operand:DI 0 "register_operand" "=r")
342 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
346 ;; FIXME: GCC should be able to synthesize this by itself as "0.0 - x".
347 (define_expand "negdf2"
348 [(set (match_operand:DF 0 "register_operand" "=r")
349 (minus:DF (match_dup 2)
350 (match_operand:DF 1 "register_operand" "r")))]
352 "operands[2] = force_reg (DFmode, CONST0_RTX (DFmode));")
354 ;; FIXME: define_expand for absdi2?
356 (define_insn "absdf2"
357 [(set (match_operand:DF 0 "register_operand" "=r")
358 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
362 (define_insn "sqrtdf2"
363 [(set (match_operand:DF 0 "register_operand" "=r")
364 (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
368 ;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
370 (define_insn "one_cmpldi2"
371 [(set (match_operand:DI 0 "register_operand" "=r")
372 (not:DI (match_operand:DI 1 "register_operand" "r")))]
376 ;; Since we don't have cc0, we do what is recommended in the manual;
377 ;; store away the operands for use in the branch, scc or movcc insn.
378 (define_expand "cmpdi"
379 [(match_operand:DI 0 "register_operand" "")
380 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")]
384 mmix_compare_op0 = operands[0];
385 mmix_compare_op1 = operands[1];
389 (define_expand "cmpdf"
390 [(match_operand:DF 0 "register_operand" "")
391 (match_operand:DF 1 "register_operand" "")]
395 mmix_compare_op0 = operands[0];
396 mmix_compare_op1 = operands[1];
400 ;; When the user-patterns expand, the resulting insns will match the
403 ;; We can fold the signed-compare where the register value is
404 ;; already equal to (compare:CCTYPE (reg) (const_int 0)).
405 ;; We can't do that at all for floating-point, due to NaN, +0.0
406 ;; and -0.0, and we can only do it for the non/zero test of
407 ;; unsigned, so that has to be done another way.
408 ;; FIXME: Perhaps a peep2 changing CCcode to a new code, that
410 (define_insn "*cmpcc_folded"
411 [(set (match_operand:CC 0 "register_operand" "=r")
413 (match_operand:DI 1 "register_operand" "r")
415 ;; FIXME: Can we test equivalence any other way?
416 ;; FIXME: Can we fold any other way?
417 "REGNO (operands[1]) == REGNO (operands[0])"
418 "%% folded: cmp %0,%1,0")
420 (define_insn "*cmpcc"
421 [(set (match_operand:CC 0 "register_operand" "=r")
423 (match_operand:DI 1 "register_operand" "r")
424 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
429 [(set (match_operand:CC_UNS 0 "register_operand" "=r")
431 (match_operand:DI 1 "register_operand" "r")
432 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
437 [(set (match_operand:CC_FP 0 "register_operand" "=r")
439 (match_operand:DF 1 "register_operand" "r")
440 (match_operand:DF 2 "register_operand" "r")))]
444 ;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to
445 ;; make signalling compliant.
447 [(set (match_operand:CC_FPEQ 0 "register_operand" "=r")
449 (match_operand:DF 1 "register_operand" "r")
450 (match_operand:DF 2 "register_operand" "r")))]
455 [(set (match_operand:CC_FUN 0 "register_operand" "=r")
457 (match_operand:DF 1 "register_operand" "r")
458 (match_operand:DF 2 "register_operand" "r")))]
462 ;; In order to get correct rounding, we have to use SFLOT and SFLOTU for
463 ;; conversion. They do not convert to SFmode; they convert to DFmode,
464 ;; with rounding as of SFmode. They are not usable as is, but we pretend
465 ;; we have a single instruction but emit two.
467 ;; Note that this will (somewhat unexpectedly) create an inexact
468 ;; exception if rounding is necessary - has to be masked off in crt0?
469 (define_expand "floatdisf2"
470 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
472 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
473 ;; Let's use a DI scratch, since SF don't generally get into
474 ;; registers. Dunno what's best; it's really a DF, but that
475 ;; doesn't logically follow from operands in the pattern.
476 (clobber (match_scratch:DI 2 "=&r"))])]
480 if (GET_CODE (operands[0]) != MEM)
484 /* FIXME: This stack-slot remains even at -O3. There must be a
487 = validize_mem (assign_stack_temp (SFmode,
488 GET_MODE_SIZE (SFmode), 0));
489 emit_insn (gen_floatdisf2 (stack_slot, operands[1]));
490 emit_move_insn (operands[0], stack_slot);
495 (define_insn "*floatdisf2_real"
496 [(set (match_operand:SF 0 "memory_operand" "=m")
498 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
499 (clobber (match_scratch:DI 2 "=&r"))]
501 "SFLOT %2,%1\;STSF %2,%0")
503 (define_expand "floatunsdisf2"
504 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
506 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
507 ;; Let's use a DI scratch, since SF don't generally get into
508 ;; registers. Dunno what's best; it's really a DF, but that
509 ;; doesn't logically follow from operands in the pattern.
510 (clobber (scratch:DI))])]
514 if (GET_CODE (operands[0]) != MEM)
518 /* FIXME: This stack-slot remains even at -O3. Must be a better
521 = validize_mem (assign_stack_temp (SFmode,
522 GET_MODE_SIZE (SFmode), 0));
523 emit_insn (gen_floatunsdisf2 (stack_slot, operands[1]));
524 emit_move_insn (operands[0], stack_slot);
529 (define_insn "*floatunsdisf2_real"
530 [(set (match_operand:SF 0 "memory_operand" "=m")
532 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
533 (clobber (match_scratch:DI 2 "=&r"))]
535 "SFLOTU %2,%1\;STSF %2,%0")
537 ;; Note that this will (somewhat unexpectedly) create an inexact
538 ;; exception if rounding is necessary - has to be masked off in crt0?
539 (define_insn "floatdidf2"
540 [(set (match_operand:DF 0 "register_operand" "=r")
542 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
546 (define_insn "floatunsdidf2"
547 [(set (match_operand:DF 0 "register_operand" "=r")
549 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
553 (define_insn "ftruncdf2"
554 [(set (match_operand:DF 0 "register_operand" "=r")
555 (fix:DF (match_operand:DF 1 "register_operand" "r")))]
560 ;; Note that this will (somewhat unexpectedly) create an inexact
561 ;; exception if rounding is necessary - has to be masked off in crt0?
562 (define_insn "fix_truncdfdi2"
563 [(set (match_operand:DI 0 "register_operand" "=r")
564 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
569 (define_insn "fixuns_truncdfdi2"
570 [(set (match_operand:DI 0 "register_operand" "=r")
572 (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
577 ;; It doesn't seem like it's possible to have memory_operand as a
578 ;; predicate here (testcase: libgcc2 floathisf). FIXME: Shouldn't it be
579 ;; possible to do that? Bug in GCC? Anyway, this used to be a simple
580 ;; pattern with a memory_operand predicate, but was split up with a
581 ;; define_expand with the old pattern as "anonymous".
582 ;; FIXME: Perhaps with SECONDARY_MEMORY_NEEDED?
583 (define_expand "truncdfsf2"
584 [(set (match_operand:SF 0 "memory_operand" "")
585 (float_truncate:SF (match_operand:DF 1 "register_operand" "")))]
589 if (GET_CODE (operands[0]) != MEM)
591 /* FIXME: There should be a way to say: 'put this in operands[0]
592 but *after* the expanded insn'. */
595 /* There is no sane destination but a register here, if it wasn't
596 already MEM. (It's too hard to get fatal_insn to work here.) */
597 if (! REG_P (operands[0]))
598 internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\");
600 /* FIXME: This stack-slot remains even at -O3. Must be a better
603 = validize_mem (assign_stack_temp (SFmode,
604 GET_MODE_SIZE (SFmode), 0));
605 emit_insn (gen_truncdfsf2 (stack_slot, operands[1]));
606 emit_move_insn (operands[0], stack_slot);
611 (define_insn "*truncdfsf2_real"
612 [(set (match_operand:SF 0 "memory_operand" "=m")
613 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
617 ;; Same comment as for truncdfsf2.
618 (define_expand "extendsfdf2"
619 [(set (match_operand:DF 0 "register_operand" "=r")
620 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
624 if (GET_CODE (operands[1]) != MEM)
628 /* There is no sane destination but a register here, if it wasn't
629 already MEM. (It's too hard to get fatal_insn to work here.) */
630 if (! REG_P (operands[0]))
631 internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\");
633 /* FIXME: This stack-slot remains even at -O3. There must be a
636 = validize_mem (assign_stack_temp (SFmode,
637 GET_MODE_SIZE (SFmode), 0));
638 emit_move_insn (stack_slot, operands[1]);
639 emit_insn (gen_extendsfdf2 (operands[0], stack_slot));
644 (define_insn "*extendsfdf2_real"
645 [(set (match_operand:DF 0 "register_operand" "=r")
646 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
650 ;; Neither sign-extend nor zero-extend are necessary; gcc knows how to
651 ;; synthesize using shifts or and, except with a memory source and not
652 ;; completely optimal. FIXME: Actually, other bugs surface when those
653 ;; patterns are defined; fix later.
655 ;; There are no sane values with the bit-patterns of (int) 0..255 except
656 ;; 0 to use in movdfcc.
658 (define_expand "movdfcc"
659 [(set (match_operand:DF 0 "register_operand" "")
661 (match_operand 1 "comparison_operator" "")
662 (match_operand:DF 2 "mmix_reg_or_0_operand" "")
663 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
667 enum rtx_code code = GET_CODE (operands[1]);
668 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
670 if (cc_reg == NULL_RTX)
672 operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
675 (define_expand "movdicc"
676 [(set (match_operand:DI 0 "register_operand" "")
678 (match_operand 1 "comparison_operator" "")
679 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
680 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
684 enum rtx_code code = GET_CODE (operands[1]);
685 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
687 if (cc_reg == NULL_RTX)
689 operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
692 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
693 (define_insn "*movdicc_real_foldable"
694 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
696 (match_operator 2 "mmix_foldable_comparison_operator"
697 [(match_operand 3 "register_operand" "r,r,r,r")
699 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
700 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
708 (define_insn "*movdicc_real"
710 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r")
713 2 "mmix_comparison_operator"
714 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
716 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
717 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
725 (define_insn "*movdfcc_real_foldable"
727 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
730 2 "mmix_foldable_comparison_operator"
731 [(match_operand 3 "register_operand" "r ,r ,r ,r")
733 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
734 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
742 (define_insn "*movdfcc_real"
744 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
747 2 "mmix_comparison_operator"
748 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
750 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
751 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
759 ;; FIXME: scc patterns will probably help, I just skip them
760 ;; right now. Revisit.
764 (if_then_else (eq (match_dup 1) (const_int 0))
765 (label_ref (match_operand 0 "" ""))
771 = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1);
776 (if_then_else (ne (match_dup 1) (const_int 0))
777 (label_ref (match_operand 0 "" ""))
783 = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1);
788 (if_then_else (gt (match_dup 1) (const_int 0))
789 (label_ref (match_operand 0 "" ""))
795 = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1);
800 (if_then_else (le (match_dup 1) (const_int 0))
801 (label_ref (match_operand 0 "" ""))
807 = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
809 /* The head comment of optabs.c:can_compare_p says we're required to
810 implement this, so we have to clean up the mess here. */
811 if (operands[1] == NULL_RTX)
813 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
814 emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0]));
815 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
822 (if_then_else (ge (match_dup 1) (const_int 0))
823 (label_ref (match_operand 0 "" ""))
829 = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
831 /* The head comment of optabs.c:can_compare_p says we're required to
832 implement this, so we have to clean up the mess here. */
833 if (operands[1] == NULL_RTX)
835 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
836 emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0]));
837 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
844 (if_then_else (lt (match_dup 1) (const_int 0))
845 (label_ref (match_operand 0 "" ""))
851 = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);
854 (define_expand "bgtu"
856 (if_then_else (gtu (match_dup 1) (const_int 0))
857 (label_ref (match_operand 0 "" ""))
863 = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);
866 (define_expand "bleu"
868 (if_then_else (leu (match_dup 1) (const_int 0))
869 (label_ref (match_operand 0 "" ""))
875 = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);
878 (define_expand "bgeu"
880 (if_then_else (geu (match_dup 1) (const_int 0))
881 (label_ref (match_operand 0 "" ""))
887 = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);
890 (define_expand "bltu"
892 (if_then_else (ltu (match_dup 1) (const_int 0))
893 (label_ref (match_operand 0 "" ""))
899 = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);
902 (define_expand "bunordered"
904 (if_then_else (unordered (match_dup 1) (const_int 0))
905 (label_ref (match_operand 0 "" ""))
911 = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1);
913 if (operands[1] == NULL_RTX)
917 (define_expand "bordered"
919 (if_then_else (ordered (match_dup 1) (const_int 0))
920 (label_ref (match_operand 0 "" ""))
926 = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);
929 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
930 ;; there's no RTL code for it. Maybe revisit in future.
932 ;; FIXME: Odd/Even matchers?
933 (define_insn "*bCC_foldable"
936 (match_operator 1 "mmix_foldable_comparison_operator"
937 [(match_operand 2 "register_operand" "r")
939 (label_ref (match_operand 0 "" ""))
947 (match_operator 1 "mmix_comparison_operator"
948 [(match_operand 2 "mmix_reg_cc_operand" "r")
950 (label_ref (match_operand 0 "" ""))
955 (define_insn "*bCC_inverted_foldable"
958 (match_operator 1 "mmix_foldable_comparison_operator"
959 [(match_operand 2 "register_operand" "r")
962 (label_ref (match_operand 0 "" ""))))]
963 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
967 (define_insn "*bCC_inverted"
970 (match_operator 1 "mmix_comparison_operator"
971 [(match_operand 2 "mmix_reg_cc_operand" "r")
974 (label_ref (match_operand 0 "" ""))))]
975 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
978 (define_expand "call"
979 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
980 (match_operand 1 "general_operand" ""))
981 (use (match_operand 2 "general_operand" ""))
982 (clobber (match_dup 4))])
983 (set (match_dup 4) (match_dup 3))]
987 /* Since the epilogue 'uses' the return address, and it is clobbered
988 in the call, and we set it back after every call (all but one setting
989 will be optimized away), integrity is maintained. */
991 = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
993 /* FIXME: There's a bug in gcc which causes NULL to be passed as
994 operand[2] when we get out of registers, which later confuses gcc.
995 Work around it by replacing it with const_int 0. Possibly documentation
997 if (operands[2] == NULL_RTX)
998 operands[2] = const0_rtx;
1000 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1003 (define_expand "call_value"
1004 [(parallel [(set (match_operand 0 "" "")
1005 (call (match_operand:QI 1 "memory_operand" "")
1006 (match_operand 2 "general_operand" "")))
1007 (use (match_operand 3 "general_operand" ""))
1008 (clobber (match_dup 5))])
1009 (set (match_dup 5) (match_dup 4))]
1013 /* Since the epilogue 'uses' the return address, and it is clobbered
1014 in the call, and we set it back after every call (all but one setting
1015 will be optimized away), integrity is maintained. */
1017 = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1019 /* FIXME: See 'call'. */
1020 if (operands[3] == NULL_RTX)
1021 operands[3] = const0_rtx;
1023 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
1024 *next* argument register, not the number of arguments in registers.
1025 (There used to be code here where that mattered.) */
1027 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1030 ;; Don't use 'p' here. A 'p' must stand first in constraints, or reload
1031 ;; messes up, not registering the address for reload. Several C++
1032 ;; test-cases, including g++.brendan/crash40.C. FIXME: This is arguably a
1033 ;; bug in gcc. Note line ~2612 in reload.c, that does things on the
1034 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1037 ;; /* All necessary reloads for an address_operand
1038 ;; were handled in find_reloads_address. */>>
1039 ;; Sorry, I have not dug deeper. If symbolic addresses are used
1040 ;; rarely compared to addresses in registers, disparaging the
1041 ;; first ("p") alternative by adding ? in the first operand
1042 ;; might do the trick. We define 'U' as a synonym to 'p', but without the
1043 ;; caveats (and very small advantages) of 'p'.
1044 (define_insn "*call_real"
1046 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1047 (match_operand 1 "" ""))
1048 (use (match_operand 2 "" ""))
1049 (clobber (reg:DI MMIX_rJ_REGNUM))]
1055 (define_insn "*call_value_real"
1056 [(set (match_operand 0 "register_operand" "=r,r")
1058 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1059 (match_operand 2 "" "")))
1060 (use (match_operand 3 "" ""))
1061 (clobber (reg:DI MMIX_rJ_REGNUM))]
1067 ;; I hope untyped_call and untyped_return are not needed for MMIX.
1068 ;; Users of Objective C will notice.
1070 ;; FIXME: Add "return" pattern where the epilogue is just "pop
1079 [(set (pc) (label_ref (match_operand 0 "" "")))]
1083 (define_insn "indirect_jump"
1084 [(set (pc) (match_operand 0 "address_operand" "p"))]
1088 ;; FIXME: This is just a jump, and should be expanded to one.
1089 (define_insn "tablejump"
1090 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1091 (use (label_ref (match_operand 1 "" "")))]
1095 ;; The only peculiar thing is that the register stack has to be unwound at
1096 ;; nonlocal_goto_receiver. At each function that has a nonlocal label, we
1097 ;; save at function entry the location of the "alpha" register stack
1098 ;; pointer, rO, in a stack slot known to that function (right below where
1099 ;; the frame-pointer would be located).
1100 ;; In the nonlocal goto receiver, we unwind the register stack by a series
1101 ;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
1102 ;; should call abort.)
1103 (define_expand "nonlocal_goto_receiver"
1104 [(parallel [(unspec_volatile [(match_dup 0)] 1)
1105 (clobber (scratch:DI))
1106 (clobber (reg:DI MMIX_rJ_REGNUM))])
1107 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 1))]
1112 = validize_mem (gen_rtx_MEM (Pmode,
1113 plus_constant (frame_pointer_rtx, -24)));
1114 operands[0] = XEXP (tem, 0);
1116 = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1118 /* Mark this function as containing a landing-pad. */
1119 cfun->machine->has_landing_pad = 1;
1122 ;; FIXME: Do we need to keep this in memory? Can GCC counter our
1123 ;; expectations and use saved registers to keep the slot address in,
1124 ;; "across" the exception or goto? Anyway, we need to make sure the value
1125 ;; ends up in a non-local register, so best is to load it ourselves.
1126 (define_insn "*nonlocal_goto_receiver_expanded"
1127 [(unspec_volatile [(match_operand:DI 0 "address_operand" "p")] 1)
1128 (clobber (match_scratch:DI 1 "=&r"))
1129 (clobber (reg:DI MMIX_rJ_REGNUM))]
1131 "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
1132 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:")
1134 (define_insn "*Naddu"
1135 [(set (match_operand:DI 0 "register_operand" "=r")
1136 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1137 (match_operand:DI 2 "const_int_operand" "n"))
1138 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
1139 "GET_CODE (operands[2]) == CONST_INT
1140 && (INTVAL (operands[2]) == 2
1141 || INTVAL (operands[2]) == 4
1142 || INTVAL (operands[2]) == 8
1143 || INTVAL (operands[2]) == 16)"
1146 (define_insn "*andn"
1147 [(set (match_operand:DI 0 "register_operand" "=r")
1149 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1150 (match_operand:DI 2 "register_operand" "r")))]
1154 (define_insn "*nand"
1155 [(set (match_operand:DI 0 "register_operand" "=r")
1157 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1158 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1163 [(set (match_operand:DI 0 "register_operand" "=r")
1165 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1166 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1170 (define_insn "*nxor"
1171 [(set (match_operand:DI 0 "register_operand" "=r")
1173 (xor:DI (match_operand:DI 1 "register_operand" "%r")
1174 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1178 (define_insn "sync_icache"
1179 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1180 (match_operand:DI 1 "const_int_operand" "I")] 0)]
1186 ;; indent-tabs-mode: t