OSDN Git Service

* Makefile.in (C_COMMON_H): Fix.
[pf3gnuchains/gcc-fork.git] / gcc / config / v850 / v850.md
index 42a95db..354dc11 100644 (file)
@@ -1,7 +1,6 @@
 ;; GCC machine description for NEC V850
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
-
-;;   Contributed by Jeff Law (law@cygnus.com).
+;; Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+;; Contributed by Jeff Law (law@cygnus.com).
 
 ;; This file is part of GNU CC.
 
 (define_attr "length" ""
   (const_int 200))
 
+(define_attr "long_calls" "yes,no"
+  (const (if_then_else (symbol_ref "TARGET_LONG_CALLS")
+                      (const_string "yes")
+                      (const_string "no"))))
+           
 ;; Types of instructions (for scheduling purposes).
 
 (define_attr "type" "load,mult,other"
               || CONST_OK_FOR_K (INTVAL (operands[1]))
               || CONST_OK_FOR_L (INTVAL (operands[1])))))
     {
-      rtx high;
       rtx temp;
 
       if (reload_in_progress || reload_completed)
       else
        temp = gen_reg_rtx (SImode);
 
-      emit_insn (gen_rtx (SET, SImode, temp,
-                          gen_rtx (HIGH, SImode, operand1)));
-      emit_insn (gen_rtx (SET, SImode, operand0,
-                          gen_rtx (LO_SUM, SImode, temp, operand1)));
+      emit_insn (gen_rtx_SET (SImode, temp,
+                             gen_rtx_HIGH (SImode, operand1)));
+      emit_insn (gen_rtx_SET (SImode, operand0,
+                             gen_rtx_LO_SUM (SImode, temp, operand1)));
       DONE;
     }
 }")
   int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff);
 
   rtx xoperands[2];
-  xoperands[0] = gen_rtx (MEM, QImode,
-                         plus_constant (XEXP (operands[0], 0), log2 / 8));
+  xoperands[0] = gen_rtx_MEM (QImode,
+                             plus_constant (XEXP (operands[0], 0), log2 / 8));
   xoperands[1] = GEN_INT (log2 % 8);
   output_asm_insn (\"clr1 %1,%0\", xoperands);
   return \"\";
   int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff);
 
   rtx xoperands[2];
-  xoperands[0] = gen_rtx (MEM, QImode,
-                         plus_constant (XEXP (operands[0], 0), log2 / 8));
+  xoperands[0] = gen_rtx_MEM (QImode,
+                             plus_constant (XEXP (operands[0], 0), log2 / 8));
   xoperands[1] = GEN_INT (log2 % 8);
   output_asm_insn (\"clr1 %1,%0\", xoperands);
   return \"\";
   else
     {
       rtx xoperands[2];
-      xoperands[0] = gen_rtx (MEM, QImode,
-                             plus_constant (XEXP (operands[0], 0), log2 / 8));
+      xoperands[0] = gen_rtx_MEM (QImode,
+                                 plus_constant (XEXP (operands[0], 0),
+                                                log2 / 8));
       xoperands[1] = GEN_INT (log2 % 8);
       output_asm_insn (\"set1 %1,%0\", xoperands);
     }
   else
     {
       rtx xoperands[2];
-      xoperands[0] = gen_rtx (MEM, QImode,
-                             plus_constant (XEXP (operands[0], 0), log2 / 8));
+      xoperands[0] = gen_rtx_MEM (QImode,
+                                 plus_constant (XEXP (operands[0], 0),
+                                                log2 / 8));
       xoperands[1] = GEN_INT (log2 % 8);
       output_asm_insn (\"set1 %1,%0\", xoperands);
     }
   else
     {
       rtx xoperands[2];
-      xoperands[0] = gen_rtx (MEM, QImode,
-                             plus_constant (XEXP (operands[0], 0), log2 / 8));
+      xoperands[0] = gen_rtx_MEM (QImode,
+                                 plus_constant (XEXP (operands[0], 0),
+                                                log2 / 8));
       xoperands[1] = GEN_INT (log2 % 8);
       output_asm_insn (\"not1 %1,%0\", xoperands);
     }
   else
     {
       rtx xoperands[2];
-      xoperands[0] = gen_rtx (MEM, QImode,
-                             plus_constant (XEXP (operands[0], 0), log2 / 8));
+      xoperands[0] = gen_rtx_MEM (QImode,
+                                 plus_constant (XEXP (operands[0], 0),
+                                                log2 / 8));
       xoperands[1] = GEN_INT (log2 % 8);
       output_asm_insn (\"not1 %1,%0\", xoperands);
     }
   if (get_attr_length (insn) == 2)
     return \"b%b1 %l0\";
   else
-    return \"b%B1 .+6\;jr %l0\";
+    return \"b%B1 .+6 ; jr %l0\";
 }"
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
   if (get_attr_length (insn) == 2)
     return \"b%B1 %l0\";
   else
-    return \"b%b1 .+6\;jr %l0\";
+    return \"b%b1 .+6 ; jr %l0\";
 }"
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
   emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1)));
   /* Load the table address into a pseudo.  */
   emit_insn (gen_movsi (tableaddress,
-                       gen_rtx (LABEL_REF, VOIDmode, operands[3])));
+                       gen_rtx_LABEL_REF (Pmode, operands[3])));
   /* Add the table address to the index.  */
   emit_insn (gen_addsi3 (reg, reg, tableaddress));
   /* Load the table entry.  */
-  mem = gen_rtx (MEM, CASE_VECTOR_MODE, reg);
-  RTX_UNCHANGING_P (mem);
+  mem = gen_rtx_MEM (CASE_VECTOR_MODE, reg);
+  RTX_UNCHANGING_P (mem) = 1;
   if (! TARGET_BIG_SWITCH)
     {
       rtx reg2 = gen_reg_rtx (HImode);
   ""
   "
 {
-  if (! call_address_operand (XEXP (operands[0], 0))
+  if (! call_address_operand (XEXP (operands[0], 0), QImode)
       || TARGET_LONG_CALLS)
     XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
-  emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1]));
+  if (TARGET_LONG_CALLS)
+    emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1]));
+  else
+    emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1]));
+  
   DONE;
 }")
 
-(define_insn "call_internal"
+(define_insn "call_internal_short"
   [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
         (match_operand:SI 1 "general_operand" "g,g"))
    (clobber (reg:SI 31))]
-  ""
+  "! TARGET_LONG_CALLS"
   "@
   jarl %0,r31
-  jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0"
-  [(set_attr "length" "4,8")])
+  jarl .+4,r31 ; add 4,r31 ; jmp %0"
+  [(set_attr "length" "4,8")]
+)
+
+(define_insn "call_internal_long"
+  [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
+        (match_operand:SI 1 "general_operand" "g,g"))
+   (clobber (reg:SI 31))]
+  "TARGET_LONG_CALLS"
+  "*
+  {
+  if (which_alternative == 0)
+    {
+      if (GET_CODE (operands[0]) == REG)
+        return \"jarl %0,r31\";
+      else
+        return \"movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11\";
+    }
+  else
+    return \"jarl .+4,r31 ; add 4,r31 ; jmp %0\";
+  }"
+  [(set_attr "length" "16,8")]
+)
 
 ;; Call subroutine, returning value in operand 0
 ;; (which must be a hard register).
   ""
   "
 {
-  if (! call_address_operand (XEXP (operands[1], 0))
+  if (! call_address_operand (XEXP (operands[1], 0), QImode)
       || TARGET_LONG_CALLS)
     XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
-  emit_call_insn (gen_call_value_internal (operands[0],
-                                          XEXP (operands[1], 0),
-                                          operands[2]));
+  if (TARGET_LONG_CALLS)
+    emit_call_insn (gen_call_value_internal_long (operands[0],
+                                                 XEXP (operands[1], 0),
+                                                 operands[2]));
+  else
+    emit_call_insn (gen_call_value_internal_short (operands[0],
+                                                  XEXP (operands[1], 0),
+                                                  operands[2]));
   DONE;
 }")
 
-(define_insn "call_value_internal"
+(define_insn "call_value_internal_short"
   [(set (match_operand 0 "" "=r,r")
        (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
              (match_operand:SI 2 "general_operand" "g,g")))
    (clobber (reg:SI 31))]
-  ""
+  "! TARGET_LONG_CALLS"
   "@
   jarl %1,r31
-  jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %1"
-  [(set_attr "length" "4,8")])
+  jarl .+4,r31 ; add 4,r31 ; jmp %1"
+  [(set_attr "length" "4,8")]
+)
+
+(define_insn "call_value_internal_long"
+  [(set (match_operand 0 "" "=r,r")
+       (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
+             (match_operand:SI 2 "general_operand" "g,g")))
+   (clobber (reg:SI 31))]
+  "TARGET_LONG_CALLS"
+  "*
+  {
+  if (which_alternative == 0)
+    {
+      if (GET_CODE (operands[1]) == REG)
+        return \"jarl %1, r31\";
+      else
+      /* Reload can generate this pattern... */
+        return \"movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11\";
+    }
+  else
+    return \"jarl .+4, r31 ; add 4, r31 ; jmp %1\";
+  }"
+  [(set_attr "length" "16,8")]
+)
 
 (define_insn "nop"
   [(const_int 0)]
  "TARGET_PROLOG_FUNCTION"
  "* return construct_save_jarl (operands[0]);
  "
- [(set_attr "length" "4")
+ [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
+                                    (const_string "16")
+                                    (const_string "4")))
   (set_attr "cc"     "clobber")])
 
 ;; This pattern will match a return RTX followed by any number of pop RTXs
    [(return)
     (set (reg:SI 3)
         (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
-    (set (match_operand:SI 2 "register_is_ok_for_epilogue" "r")
+    (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r")
         (mem:SI (plus:SI (reg:SI 3)
                          (match_operand:SI 3 "immediate_operand" "i"))))])]
  "TARGET_PROLOG_FUNCTION && TARGET_V850"
  "* return construct_restore_jr (operands[0]);
  "
- [(set_attr "length" "4")
+ [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
+                                    (const_string "12")
+                                    (const_string "4")))
   (set_attr "cc"     "clobber")])
 
 ;; Initialize an interrupt function.  Do not depend on TARGET_PROLOG_FUNCTION.
    (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))
    (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4))
    (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))]
-  "TARGET_V850"
-  "add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10"
+  "TARGET_V850 && ! TARGET_LONG_CALLS"
+  "add -16, sp ; st.w r10, 12[sp] ; jarl __save_interrupt, r10"
   [(set_attr "length" "12")
    (set_attr "cc" "clobber")])
 
 
 (define_insn "save_all_interrupt"
   [(unspec_volatile [(const_int 0)] 0)]
-  "TARGET_V850"
+  "TARGET_V850 && ! TARGET_LONG_CALLS"
   "jarl __save_all_interrupt,r10"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
 
 (define_insn "restore_all_interrupt"
   [(unspec_volatile [(const_int 0)] 1)]
-  "TARGET_V850"
+  "TARGET_V850 && ! TARGET_LONG_CALLS"
   "jarl __restore_all_interrupt,r10"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
    (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8))
    (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9))
    (clobber (reg:SI 10))]
-  "TARGET_PROLOG_FUNCTION"
+  "TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS"
   "jarl __save_r6_r9,r10"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])