OSDN Git Service

2001-07-26 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / clipper / clipper.md
index d53312d..2d2a504 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for GNU compiler, Clipper Version
-;;   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
-
+;;  Copyright (C) 1987, 1988, 1991, 1993, 1994, 1997, 1998, 1999, 2001
+;;  Free Software Foundation, Inc.
 ;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
 
 ;; This file is part of GNU CC.
@@ -17,7 +17,8 @@
 
 ;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 
 ;;- Instruction patterns.  When multiple patterns apply,
@@ -60,7 +61,7 @@
   (const_string "clobber")))
 
 ;;
-;; clipper seems to be a tradional risc processor
+;; clipper seems to be a traditional risc processor
 ;; we define a functional unit 'memory'
 ;;
 (define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0)     
   ""
   "*
 {
+  int val;
+
   if (which_alternative == 0)
     return \"cmpw   %1,%0\";
 
   if (which_alternative == 1)
-    return \"cmpi   %1,%0\";
+    {
+      val = INTVAL (operands[1]);
+      if (0 <= val && val < 16)
+       return \"cmpq   %1,%0\";
+      return \"cmpi   %1,%0\";
+    }
 
   cc_status.flags |= CC_REVERSED;      /* immediate must be first */
+
+  val = INTVAL (operands[0]);
+
+  if (0 <= val && val < 16)
+    return \"cmpq   %0,%1\";
+
   return \"cmpi   %0,%1\";
 }")
 
 ;; to recombine a mem -> mem move
 ;; 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=rf")
-       (match_operand:DF 1 "nonimmediate_operand" "rfo"))]
+  [(set (match_operand:DF 0 "register_operand" "=*rf")
+       (match_operand:DF 1 "nonimmediate_operand" "*rfo"))]
   ""
   "*
 {
     {
       rtx xops[4];
       xops[0] = operands[0];
-      xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      xops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
       xops[2] = operands[1];
-      xops[3] = adj_offsettable_operand (operands[1], 4);
+      xops[3] = adjust_address (operands[1], SImode, 4);
       output_asm_insn (\"loadw  %2,%0\;loadw  %3,%1\", xops);
       return \"\";
     }
     {
       rtx xops[4];
       xops[0] = operands[0];
-      xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      xops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
       xops[2] = operands[1];
-      xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+      xops[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
       output_asm_insn (\"movw   %2,%0\;movw   %3,%1\", xops);
       return \"\";
     }
 
 (define_insn ""
   [(set (match_operand:DF 0 "memory_operand" "=o,m")
-       (match_operand:DF 1 "register_operand" "r,f"))]
+       (match_operand:DF 1 "register_operand" "*rf,f"))]
   ""
   "*
 {
-  if (which_alternative == 0)          /* r -> o */
-    {
-      rtx xops[4];
-      xops[0] = operands[0];
-      xops[1] = adj_offsettable_operand (operands[0], 4);
-      xops[2] = operands[1];
-      xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
-      output_asm_insn (\"storw  %2,%0\;storw  %3,%1\", xops);
-      return \"\";
-    }
+  rtx xops[4];
 
-  return \"stord  %1,%0\";             /* f-> m */
+  if (REGNO (operands[1]) >= 16)       /* f -> m */
+    return \"stord  %1,%0\";
+
+  xops[0] = operands[0];               /* r -> o */
+  xops[1] = adjust_address (operands[0], SImode, 4);
+  xops[2] = operands[1];
+  xops[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+  output_asm_insn (\"storw  %2,%0\;storw  %3,%1\", xops);
+  return \"\";
 }"
 [(set_attr "type" "store,store")
  (set_attr "cc" "clobber,unchanged")])
 ;; to recombine a mem -> mem move
 ;; 
 (define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=rf")
-       (match_operand:SF 1 "nonimmediate_operand" "rfm"))]
+  [(set (match_operand:SF 0 "register_operand" "=*rf")
+       (match_operand:SF 1 "nonimmediate_operand" "*rfm"))]
   ""
   "*
 {
 
 (define_insn ""
   [(set (match_operand:SF 0 "memory_operand" "=m")
-       (match_operand:SF 1 "register_operand" "rf"))]
+       (match_operand:SF 1 "register_operand" "*rf"))]
   ""
   "*
 {
     operands[1] = force_reg (DImode, operands[1]);
 }")
 
+;; If an operand is a MEM but not offsettable, we can't load it into
+;; a register, so we must force the third alternative to be the one
+;; reloaded.  Hence we show the first as more expensive.
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+  [(set (match_operand:DI 0 "register_operand" "=?r,r,r")
        (match_operand:DI 1 "general_operand"   "r,n,o"))]
   ""
   "*
 {
   rtx xoperands[2],yoperands[2];
 
-  xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  xoperands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
 
   if (which_alternative == 0)          /* r -> r */
     {
       output_asm_insn (\"movw   %1,%0\", operands);
-      xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+      xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
       output_asm_insn (\"movw   %1,%0\", xoperands);
       return \"\";
     }
        abort ();
 
       yoperands[0] = operands[0];
-      yoperands[1] = gen_rtx (CONST_INT, VOIDmode,
-                             CONST_DOUBLE_LOW (operands[1]));
+      yoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
       output_asm_insn (\"loadi  %1,%0\", yoperands);
 
-      xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
-                             CONST_DOUBLE_HIGH (operands[1]));
+      xoperands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
       output_asm_insn (\"loadi  %1,%0\", xoperands);
       return \"\";
     }
                                        /* m -> r */
   output_asm_insn (\"loadw  %1,%0\", operands);
-  xoperands[1] = adj_offsettable_operand (operands[1], 4);
+  xoperands[1] = adjust_address (operands[1], SImode, 4);
   output_asm_insn (\"loadw  %1,%0\", xoperands);
   return \"\";
 }" 
 {
   rtx xops[4];
   xops[0] = operands[0];
-  xops[1] = adj_offsettable_operand (operands[0], 4);
+  xops[1] = adjust_address (operands[0], SImode, 4);
   xops[2] = operands[1];
-  xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+  xops[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
   output_asm_insn (\"storw  %2,%0\;storw  %3,%1\", xops);
   return \"\";
 }"
     operands[1] = force_reg (SImode, operands[1]);
 }")
 
-;; provide 2 patterns with different predicates as 'general_operand' in both
-;; positions results in a 'mem -> mem' move from combine that must be reloaded 
+;; Reject both args with `general_operand' if not reloading because a
+;; mem -> mem move that was split by 'movsi' can be recombined to
+;; mem -> mem by the combiner.
 ;;
-
+;; As a pseudo register can end up in a stack slot during reloading we must
+;; allow a r->m move for the next pattern. 
+;; The first predicate must be `general_operand' because a predicate must
+;; be true for each constraint.
+;;  
 (define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-       (match_operand:SI 1 "general_operand"   "r,m,n,i"))]
-  ""
+  [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m")
+       (match_operand:SI 1 "general_operand"  "r,m,n,i,r"))]
+  "reload_in_progress || register_operand (operands[0], SImode)"
   "*
 {
   int val;
 
   if (which_alternative == 3)          /* unknown const */
     return \"loada  %a1,%0\";
+
+  return \"storw  %1,%0\";
 }"
-[(set_attr "type" "arith,load,arith,load")
- (set_attr "cc" "set2,change0,set1,change0")])
+[(set_attr "type" "arith,load,arith,load,store")
+ (set_attr "cc" "set2,change0,set1,change0,unchanged")])
 
 
 (define_insn ""
   operands[6] = addr0;
   operands[7] = addr1;
 
-  operands[0] = gen_rtx (MEM, BLKmode, addr0);
-  operands[1] = gen_rtx (MEM, BLKmode, addr1);
+  operands[0] = replace_equiv_address (operands[0], addr0);
+  operands[1] = replace_equiv_address (operands[1], addr1);
 
   if (GET_CODE (operands[2]) != CONST_INT)
     operands[2] = force_reg (SImode, operands[2]);
   rtx xoperands[4];
 
   xoperands[0] = operands[0];
-  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   xoperands[2] = operands[2];
-  xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+  xoperands[3] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
   output_asm_insn (\"addw   %2,%0\;addwc  %3,%1\", xoperands);
   return \"\";
 }"
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "int_reg_operand" "=r,r,r")
        (plus:SI (match_operand:SI 1 "int_reg_operand" "%0,r,r")
-                (match_operand:SI 2 "nonmemory_operand" "rn,0,r")))]
+                (match_operand:SI 2 "nonmemory_operand" "rn,0,rn")))]
   ""
   "*
 {
   if (which_alternative == 2)          /* 3 address version */
-    return \"loada  [%2](%1),%0\";
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+       return \"loada  %a2(%1),%0\";
+      return \"loada  [%2](%1),%0\";
+    }
                                        /* 2 address version */
   if (GET_CODE (operands[2]) == CONST_INT)
     {
          val = -val;
 
          xops[0] = operands[0];
-         xops[1] = gen_rtx (CONST_INT, VOIDmode, val);
+         xops[1] = GEN_INT (val);
 
          if (val >= 16)
            output_asm_insn (\"subi   %1,%0\", xops);
 
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "int_reg_operand" "=r")
-       (minus:DI (match_operand:DI 1 "int_reg_operand" "%0")
+       (minus:DI (match_operand:DI 1 "int_reg_operand" "0")
                  (match_operand:DI 2 "int_reg_operand" "r")))]
   ""
   "*
   rtx xoperands[4];
 
   xoperands[0] = operands[0];
-  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   xoperands[2] = operands[2];
-  xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+  xoperands[3] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
   output_asm_insn (\"subw   %2,%0\;subwc  %3,%1\", xoperands);
   return \"\";
 }"
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   "shlw   %2,%0"
  [(set_attr "type" "arith")])
 
-(define_insn "lshldi3"
-  [(set (match_operand:DI 0 "int_reg_operand" "=r,r")
-       (lshift:DI (match_operand:DI 1 "int_reg_operand" "0,0")
-                  (match_operand:SI 2 "nonmemory_operand" "r,n")))]
-  ""
-  "@
-   shll   %2,%0
-   shlli  %2,%0"
- [(set_attr "type" "arith")])
-
-(define_insn "lshlsi3"
-  [(set (match_operand:SI 0 "int_reg_operand" "=r,r")
-       (lshift:SI (match_operand:SI 1 "int_reg_operand" "0,0")
-                  (match_operand:SI 2 "nonmemory_operand" "r,n")))]
-  ""
-  "@
-   shlw   %2,%0
-   shli   %2,%0"
- [(set_attr "type" "arith")])
 
 ;;
 ;; rotate insn
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT)
-    operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+    operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
 }")
 
 (define_insn ""
   ""
   "call   sp,%1")
 
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+  [(parallel [(call (match_operand 0 "" "")
+                   (const_int 0))
+             (match_operand 1 "" "")
+             (match_operand 2 "" "")])]
+  ""
+  "
+{
+  int i;
+
+  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+
+  for (i = 0; i < XVECLEN (operands[2], 0); i++)
+    {
+      rtx set = XVECEXP (operands[2], 0, i);
+      emit_move_insn (SET_DEST (set), SET_SRC (set));
+    }
+
+  /* The optimizer does not know that the call sets the function value
+     registers we stored in the result block.  We avoid problems by
+     claiming that all hard registers are used and clobbered at this
+     point.  */
+  emit_insn (gen_blockage ());
+
+  DONE;
+}")
+
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
+;; all of memory.  This blocks insns from being moved across this point.
+
+(define_insn "blockage"
+  [(unspec_volatile [(const_int 0)] 0)]
+  ""
+  "")
+
 (define_insn "indirect_jump"
   [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
   ""
 ;; These patters are jump_insns that do not allow output reloads and clipper
 ;; can only decrement and test registers.
 ;;
-
-\f
-;;- Local variables:
-;;- mode:c
-;;- comment-start: ";;- "
-;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
-;;- eval: (modify-syntax-entry ?[ "(]")
-;;- eval: (modify-syntax-entry ?] ")[")
-;;- eval: (modify-syntax-entry ?{ "(}")
-;;- eval: (modify-syntax-entry ?} "){")
-;;- End: