]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/mmix/mmix.md
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / mmix / mmix.md
index cf2ae140614ffca8ebb6df653882a07cfdbc7591..aa878af0f825e983f9c711f430fcdef2f586d6da 100644 (file)
@@ -1,23 +1,23 @@
 ;; GCC machine description for MMIX
-;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
+;; Free Software Foundation, Inc.
 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
 
-;; This file is part of GNU CC.
+;; This file is part of GCC.
 
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 ;; The original PO technology requires these to be ordered by speed,
 ;; so that assigner will pick the fastest.
 
 (define_constants
   [(MMIX_rJ_REGNUM 259)
+   (MMIX_rR_REGNUM 260)
    (MMIX_fp_rO_OFFSET -24)]
 )
+\f
+;; Operand and operator predicates.
 
+(include "predicates.md")
+\f
 ;; FIXME: Can we remove the reg-to-reg for smaller modes?  Shouldn't they
 ;; be synthesized ok?
 (define_insn "movqi"
    STOU %1,%0
    %r0%I1")
 \f
+;; We need to be able to move around the values used as condition codes.
+;; First spotted as reported in
+;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> due to
+;; changes in loop optimization.  The file machmode.def says they're of
+;; size 4 QI.  Valid bit-patterns correspond to integers -1, 0 and 1, so
+;; we treat them as signed entities; see mmix-modes.def.  The following
+;; expanders should cover all MODE_CC modes, and expand for this pattern.
+(define_insn "*movcc_expanded"
+  [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
+       (match_operand 1 "nonimmediate_operand"  "r,r,x,m,r"))]
+  "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC
+   && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC"
+  "@
+   SET %0,%1
+   PUT %0,%1
+   GET %0,%1
+   LDT %0,%1
+   STT %1,%0")
+
+(define_expand "movcc"
+  [(set (match_operand:CC 0 "nonimmediate_operand" "")
+       (match_operand:CC 1 "nonimmediate_operand" ""))]
+  ""
+  "")
+
+(define_expand "movcc_uns"
+  [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
+       (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
+  ""
+  "")
+
+(define_expand "movcc_fp"
+  [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
+       (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
+  ""
+  "")
+
+(define_expand "movcc_fpeq"
+  [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
+       (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
+  ""
+  "")
+
+(define_expand "movcc_fun"
+  [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
+       (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
+  ""
+  "")
+\f
 (define_insn "adddi3"
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
        (plus:DI
 ;; One day we might persuade GCC to expand divisions with constants the
 ;; way MMIX does; giving the remainder the sign of the divisor.  But even
 ;; then, it might be good to have an option to divide the way "everybody
-;; else" does.  Perhaps then, this option can be on by default.  Until
-;; then, we do division and modulus in a library function.
+;; else" does.  Perhaps then, this option can be on by default.  However,
+;; it's not likely to happen because major (C, C++, Fortran) language
+;; standards in effect at 2002-04-29 reportedly demand that the sign of
+;; the remainder must follow the sign of the dividend.
 
 (define_insn "divmoddi4"
   [(set (match_operand:DI 0 "register_operand" "=r")
          (div:DI (match_operand:DI 1 "register_operand" "r")
                  (match_operand:DI 2 "register_operand" "r")))
      (clobber (scratch:DI))
-     (clobber (scratch:DI))])]
+     (clobber (scratch:DI))
+     (clobber (reg:DI MMIX_rR_REGNUM))])]
   "! TARGET_KNUTH_DIVISION"
   "")
 
        (div:DI (match_operand:DI 1 "register_operand" "r,r")
                (match_operand:DI 2 "register_operand" "1,r")))
    (clobber (match_scratch:DI 3 "=1,1"))
-   (clobber (match_scratch:DI 4 "=2,2"))]
+   (clobber (match_scratch:DI 4 "=2,2"))
+   (clobber (reg:DI MMIX_rR_REGNUM))]
   "! TARGET_KNUTH_DIVISION"
   "@
    SETL %0,1
@@ -293,7 +351,8 @@ DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
          (mod:DI (match_operand:DI 1 "register_operand" "r")
                  (match_operand:DI 2 "register_operand" "r")))
      (clobber (scratch:DI))
-     (clobber (scratch:DI))])]
+     (clobber (scratch:DI))
+     (clobber (reg:DI MMIX_rR_REGNUM))])]
   "! TARGET_KNUTH_DIVISION"
   "")
 
@@ -304,7 +363,8 @@ DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
        (mod:DI (match_operand:DI 1 "register_operand" "r,r")
                (match_operand:DI 2 "register_operand" "1,r")))
    (clobber (match_scratch:DI 3 "=1,1"))
-   (clobber (match_scratch:DI 4 "=2,2"))]
+   (clobber (match_scratch:DI 4 "=2,2"))
+   (clobber (reg:DI MMIX_rR_REGNUM))]
   "! TARGET_KNUTH_DIVISION"
   "@
    SETL %0,0
@@ -341,13 +401,22 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   ""
   "NEGU %0,0,%1")
 
-;; FIXME: GCC should be able to synthesize this by itself as "0.0 - x".
 (define_expand "negdf2"
+  [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
+                   (neg:DF (match_operand:DF 1 "register_operand" "r")))
+              (use (match_dup 2))])]
+  ""
+{
+  /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0.  */
+  operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
+})
+
+(define_insn "*expanded_negdf2"
   [(set (match_operand:DF 0 "register_operand" "=r")
-       (minus:DF (match_dup 2)
-               (match_operand:DF 1 "register_operand" "r")))]
+        (neg:DF (match_operand:DF 1 "register_operand" "r")))
+   (use (match_operand:DI 2 "register_operand" "r"))]
   ""
-  "operands[2] = force_reg (DFmode, CONST0_RTX (DFmode));")
+  "XOR %0,%1,%2")
 
 ;; FIXME: define_expand for absdi2?
 
@@ -412,7 +481,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
         (const_int 0)))]
   ;; FIXME: Can we test equivalence any other way?
   ;; FIXME: Can we fold any other way?
-  "REGNO (operands[1]) == REGNO (operands[0])"
+  "REG_P (operands[0]) && REG_P (operands[1])
+   && REGNO (operands[1]) == REGNO (operands[0])"
   "%% folded: cmp %0,%1,0")
 
 (define_insn "*cmpcc"
@@ -567,7 +637,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
 (define_insn "fixuns_truncdfdi2"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unsigned_fix:DI
-        (unsigned_fix:DF (match_operand:DF 1 "register_operand" "r"))))]
+        (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
   ""
   ;; ROUND_OFF
   "FIXU %0,1,%1")
@@ -667,7 +737,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
                                     mmix_compare_op1);
   if (cc_reg == NULL_RTX)
     FAIL;
-  operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
+  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
 }")
 
 (define_expand "movdicc"
@@ -684,7 +754,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
                                     mmix_compare_op1);
   if (cc_reg == NULL_RTX)
     FAIL;
-  operands[1] = gen_rtx (code, VOIDmode, cc_reg, const0_rtx);
+  operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
 }")
 
 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
@@ -692,7 +762,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
        (if_then_else:DI
         (match_operator 2 "mmix_foldable_comparison_operator"
-                        [(match_operand 3 "register_operand" "r,r,r,r")
+                        [(match_operand:DI 3 "register_operand" "r,r,r,r")
                          (const_int 0)])
         (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
         (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
@@ -703,7 +773,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
    ZS%d2 %0,%3,%1
    ZS%D2 %0,%3,%4")
 
-(define_insn "*movdicc_real"
+(define_insn "*movdicc_real_reversible"
   [(set
     (match_operand:DI 0 "register_operand"        "=r ,r ,r ,r")
     (if_then_else:DI
@@ -713,20 +783,35 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
       (const_int 0)])
      (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
      (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
-  ""
+  "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
   "@
    CS%d2 %0,%3,%1
    CS%D2 %0,%3,%4
    ZS%d2 %0,%3,%1
    ZS%D2 %0,%3,%4")
 
+(define_insn "*movdicc_real_nonreversible"
+  [(set
+    (match_operand:DI 0 "register_operand"        "=r ,r")
+    (if_then_else:DI
+     (match_operator
+      2 "mmix_comparison_operator"
+      [(match_operand 3 "mmix_reg_cc_operand"      "r ,r")
+      (const_int 0)])
+     (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
+     (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
+  "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
+  "@
+   CS%d2 %0,%3,%1
+   ZS%d2 %0,%3,%1")
+
 (define_insn "*movdfcc_real_foldable"
   [(set
     (match_operand:DF 0 "register_operand"     "=r  ,r  ,r  ,r")
     (if_then_else:DF
      (match_operator
       2 "mmix_foldable_comparison_operator"
-      [(match_operand 3 "register_operand"      "r  ,r  ,r  ,r")
+      [(match_operand:DI 3 "register_operand"   "r  ,r  ,r  ,r")
       (const_int 0)])
      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
@@ -737,7 +822,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
    ZS%d2 %0,%3,%1
    ZS%D2 %0,%3,%4")
 
-(define_insn "*movdfcc_real"
+(define_insn "*movdfcc_real_reversible"
   [(set
     (match_operand:DF 0 "register_operand"     "=r  ,r  ,r  ,r")
     (if_then_else:DF
@@ -747,13 +832,28 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
       (const_int 0)])
      (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0  ,rGM,GM")
      (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,rGM,GM ,rGM")))]
-  ""
+  "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
   "@
    CS%d2 %0,%3,%1
    CS%D2 %0,%3,%4
    ZS%d2 %0,%3,%1
    ZS%D2 %0,%3,%4")
 
+(define_insn "*movdfcc_real_nonreversible"
+  [(set
+    (match_operand:DF 0 "register_operand"     "=r  ,r")
+    (if_then_else:DF
+     (match_operator
+      2 "mmix_comparison_operator"
+      [(match_operand 3 "mmix_reg_cc_operand"   "r  ,r")
+      (const_int 0)])
+     (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
+     (match_operand:DF 4 "mmix_reg_or_0_operand" "0  ,GM")))]
+  "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
+  "@
+   CS%d2 %0,%3,%1
+   ZS%d2 %0,%3,%1")
+
 ;; FIXME: scc patterns will probably help, I just skip them
 ;; right now.  Revisit.
 \f
@@ -805,7 +905,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
     = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
 
   /* The head comment of optabs.c:can_compare_p says we're required to
-     implement this, so we have to clean up the mess here. */
+     implement this, so we have to clean up the mess here.  */
   if (operands[1] == NULL_RTX)
     {
       /* FIXME: Watch out for sharing/unsharing of rtx:es.  */
@@ -827,7 +927,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
     = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
 
   /* The head comment of optabs.c:can_compare_p says we're required to
-     implement this, so we have to clean up the mess here. */
+     implement this, so we have to clean up the mess here.  */
   if (operands[1] == NULL_RTX)
     {
       /* FIXME: Watch out for sharing/unsharing of rtx:es.  */
@@ -932,7 +1032,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   [(set (pc)
        (if_then_else
         (match_operator 1 "mmix_foldable_comparison_operator"
-                        [(match_operand 2 "register_operand" "r")
+                        [(match_operand:DI 2 "register_operand" "r")
                          (const_int 0)])
         (label_ref (match_operand 0 "" ""))
         (pc)))]
@@ -954,7 +1054,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   [(set (pc)
        (if_then_else
         (match_operator 1 "mmix_foldable_comparison_operator"
-                        [(match_operand 2 "register_operand" "r")
+                        [(match_operand:DI 2 "register_operand" "r")
                          (const_int 0)])
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
@@ -982,11 +1082,22 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   ""
   "
 {
+  /* The caller checks that the operand is generally valid as an
+     address, but at -O0 nothing makes sure that it's also a valid
+     call address for a *call*; a mmix_symbolic_or_address_operand.
+     Force into a register if it isn't.  */
+  if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
+                                        GET_MODE (XEXP (operands[0], 0))))
+    operands[0]
+      = replace_equiv_address (operands[0],
+                              force_reg (Pmode, XEXP (operands[0], 0)));
+
   /* Since the epilogue 'uses' the return address, and it is clobbered
      in the call, and we set it back after every call (all but one setting
      will be optimized away), integrity is maintained.  */
   operands[3]
-    = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+    = mmix_get_hard_reg_initial_val (Pmode,
+                                    MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
 
   /* FIXME: There's a bug in gcc which causes NULL to be passed as
      operand[2] when we get out of registers, which later confuses gcc.
@@ -1008,11 +1119,22 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   ""
   "
 {
+  /* The caller checks that the operand is generally valid as an
+     address, but at -O0 nothing makes sure that it's also a valid
+     call address for a *call*; a mmix_symbolic_or_address_operand.
+     Force into a register if it isn't.  */
+  if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
+                                        GET_MODE (XEXP (operands[1], 0))))
+    operands[1]
+      = replace_equiv_address (operands[1],
+                              force_reg (Pmode, XEXP (operands[1], 0)));
+
   /* Since the epilogue 'uses' the return address, and it is clobbered
      in the call, and we set it back after every call (all but one setting
      will be optimized away), integrity is maintained.  */
   operands[4]
-    = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+    = mmix_get_hard_reg_initial_val (Pmode,
+                                    MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
 
   /* FIXME: See 'call'.  */
   if (operands[3] == NULL_RTX)
@@ -1027,7 +1149,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
 
 ;; Don't use 'p' here.  A 'p' must stand first in constraints, or reload
 ;; messes up, not registering the address for reload.  Several C++
-;; test-cases, including g++.brendan/crash40.C.  FIXME: This is arguably a
+;; testcases, including g++.brendan/crash40.C.  FIXME: This is arguably a
 ;; bug in gcc.  Note line ~2612 in reload.c, that does things on the
 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
 ;; ~3017 that says:
@@ -1063,10 +1185,31 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
    PUSHGO $%p3,%a1")
 
 ;; I hope untyped_call and untyped_return are not needed for MMIX.
-;; Users of Objective C will notice.
+;; Users of Objective-C will notice.
+
+; Generated by GCC.
+(define_expand "return"
+  [(return)]
+  "mmix_use_simple_return ()"
+  "")
+
+; Generated by the epilogue expander.
+(define_insn "*expanded_return"
+  [(return)]
+  ""
+  "POP %.,0")
 
-;; FIXME:  Add "return" pattern where the epilogue is just "pop
-;; 0,0" or similar.
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "mmix_expand_prologue (); DONE;")
+
+; Note that the (return) from the expander itself is always the last insn
+; in the epilogue.
+(define_expand "epilogue"
+  [(return)]
+  ""
+  "mmix_expand_epilogue ();")
 
 (define_insn "nop"
   [(const_int 0)]
@@ -1097,7 +1240,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
 ;; the frame-pointer would be located).
 ;; In the nonlocal goto receiver, we unwind the register stack by a series
 ;; of "pop 0,0" until rO equals the saved value.  (If it goes lower, we
-;; should call abort.)
+;; should die with a trap.)
 (define_expand "nonlocal_goto_receiver"
   [(parallel [(unspec_volatile [(const_int 0)] 1)
              (clobber (scratch:DI))
@@ -1107,7 +1250,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
   "
 {
   operands[0]
-    = get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+    = mmix_get_hard_reg_initial_val (Pmode,
+                                    MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
 
   /* Mark this function as containing a landing-pad.  */
   cfun->machine->has_landing_pad = 1;