h8300.c (interrupt_handler): Renamed from pragma_interrupt.
authorJeff Law <law@gcc.gnu.org>
Mon, 1 Apr 1996 18:48:52 +0000 (11:48 -0700)
committerJeff Law <law@gcc.gnu.org>
Mon, 1 Apr 1996 18:48:52 +0000 (11:48 -0700)
        * h8300.c (interrupt_handler): Renamed from pragma_interrupt.
        All references changed.
        (function_prologue): Set interrupt_handler if the current
        function has the "interrrupt-handler" attribute.
        (small_call_insn_operand): New function.
        (h8300_interrrupt_function_p): New function.
        (h8300_funcvec_function_p): New function.
        (h8300_valid_machine_decl_attribute): New function.
        * h8300.h (VALID_MACHINE_DECL_ATTRIBUTE): Define.
        * h8300.md (call insns): Handle calls through the
        function vector.  Indirect calls and calls through
        the function vector have a length of two bytes.

From-SVN: r11650

gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.h
gcc/config/h8300/h8300.md

index cadff01..6a85ecb 100644 (file)
@@ -40,11 +40,16 @@ Boston, MA 02111-1307, USA.  */
 void print_operand_address ();
 char *index ();
 
+static int h8300_interrupt_function_p PROTO ((tree));
+static int h8300_funcvec_function_p PROTO ((tree));
+
 /* CPU_TYPE, says what cpu we're compiling for.  */
 int cpu_type;
 
-/* True if a #pragma interrupt has been seen for the current function.  */
-int pragma_interrupt;
+/* True if the current function is an interrupt handler
+   (either via #pragma or an attribute specification).  */
+int interrupt_handler;
+
 
 /* True if a #pragma saveall has been seen for the current function.  */
 int pragma_saveall;
@@ -110,7 +115,7 @@ byte_reg (x, b)
 
 #define WORD_REG_USED(regno)                                   \
   (regno < 7 &&                                                        \
-   (pragma_interrupt                                           \
+   (interrupt_handler                                          \
     || pragma_saveall                                          \
     || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])        \
     || (regs_ever_live[regno] & !call_used_regs[regno])))
@@ -190,6 +195,9 @@ function_prologue (file, size)
   int idx;
   extra_pop = 0;
 
+  if (h8300_interrupt_function_p (current_function_decl))
+    interrupt_handler = 1;
+
   if (current_function_anonymous_args && TARGET_QUICKCALL)
     {
       /* Push regs as if done by caller, and move around return address.  */
@@ -325,13 +333,13 @@ function_epilogue (file, size)
     }
   else
     {
-      if (pragma_interrupt)
+      if (interrupt_handler)
        fprintf (file, "\trte\n");
       else
        fprintf (file, "\trts\n");
     }
 
-  pragma_interrupt = 0;
+  interrupt_handler = 0;
   pragma_saveall = 0;
 
   current_function_anonymous_args = 0;
@@ -470,6 +478,32 @@ call_insn_operand (op, mode)
   return 0;
 }
 
+/* Return true if OP is a valid call operand, and OP represents
+   an operand for a small call (4 bytes instead of 6 bytes).  */
+
+int
+small_call_insn_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (GET_CODE (op) == MEM)
+    {
+      rtx inside = XEXP (op, 0);
+
+      /* Register indirect is a small call.  */
+      if (register_operand (inside, Pmode))
+       return 1;
+
+      /* A call through the function vector is a small
+        call too.  */
+      if (GET_CODE (inside) == SYMBOL_REF
+         && SYMBOL_REF_FLAG (inside))
+       return 1;
+    }
+  /* Otherwise it's a large call.  */
+  return 0;
+}
+
 /* Return true if OP is a valid jump operand.  */
 
 int
@@ -569,7 +603,7 @@ handle_pragma (file, c)
       pbuf[psize] = 0;
 
       if (strcmp (pbuf, "interrupt") == 0)
-       pragma_interrupt = 1;
+       interrupt_handler = 1;
       else if (strcmp (pbuf, "saveall") == 0)
        pragma_saveall = 1;
 
@@ -2065,3 +2099,65 @@ fix_bit_operand (operands, what, type)
   }
   return 1;
 }
+
+
+/* Return nonzero if FUNC is an interrupt function as specified
+   by the "interrupt" attribute.  */
+
+static int
+h8300_interrupt_function_p (func)
+     tree func;
+{
+  tree a;
+
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    return 0;
+
+  a = lookup_attribute ("interrupt-handler", DECL_MACHINE_ATTRIBUTES (func));
+  return a != NULL_TREE;
+}
+
+/* Return nonzero if FUNC is a function that should be called
+   through the function vector.  */
+
+int
+h8300_funcvec_function_p (func)
+     tree func;
+{
+  tree a;
+
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    return 0;
+
+  a = lookup_attribute ("function-vector", DECL_MACHINE_ATTRIBUTES (func));
+  return a != NULL_TREE;
+}
+
+/* Return nonzero if ATTR is a valid attribute for DECL.
+   ATTRIBUTES are any existing attributes and ARGS are the arguments
+   supplied with ATTR.
+
+   Supported attributes:
+
+   interrupt-handler: output a prologue and epilogue suitable for an
+   interrupt handler.
+
+   function-vector: This function should be called through the
+   function vector.  */
+
+int
+h8300_valid_machine_decl_attribute (decl, attributes, attr, args)
+     tree decl;
+     tree attributes;
+     tree attr;
+     tree args;
+{
+  if (args != NULL_TREE)
+    return 0;
+
+  if (is_attribute_p ("interrupt-handler", attr)
+      || is_attribute_p ("function-vector", attr))
+    return TREE_CODE (decl) == FUNCTION_DECL;
+  return 0;
+}
+
index b1a44a7..197d814 100644 (file)
@@ -932,6 +932,13 @@ extern int current_function_anonymous_args;
    so give the MEM rtx a byte's mode.  */
 #define FUNCTION_MODE QImode
 
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+   is a valid machine specific attribute for DECL.
+   The attributes in ATTRIBUTES have previously been assigned to DECL.  */
+extern int h8300_valid_machine_decl_attribute ();
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+h8300_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
 /* Compute the cost of computing a constant rtl expression RTX
    whose rtx-code is CODE.  The body of this macro is a portion
    of a switch statement.  If the code is computed here,
@@ -1081,6 +1088,14 @@ dtors_section()                                          \
     }                                          \
 }                                               
 
+/* If we are referencing a function that is supposed to be called
+   through the function vector, the SYMBOL_REF_FLAG in the rtl
+   so the call patterns can generate the correct code.  */
+#define ENCODE_SECTION_INFO(DECL)  \
+  if (TREE_CODE (DECL) == FUNCTION_DECL \
+      && h8300_funcvec_function_p (DECL)) \
+    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
 
index a68d54c..509c960 100644 (file)
   [(call (match_operand:QI 0 "call_insn_operand" "or")
         (match_operand:HI 1 "general_operand" "g"))]
   ""
-  "jsr %0"
+  "*
+{
+  if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+      && SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+    return \"jsr\\t\@%0:8\";
+  else
+    return \"jsr\\t%0\";
+}"
   [(set_attr "type" "call")
    (set_attr "cc" "clobber")
-   (set_attr "length" "4")])
+   (set (attr "length")
+     (if_then_else (match_operand:QI 0 "small_call_insn_operand" "")
+                  (const_int 4)
+                  (const_int 8)))])
 
 ;; Call subroutine, returning value in operand 0
 ;; (which must be a hard register).
        (call (match_operand:QI 1 "call_insn_operand" "or")
              (match_operand:HI 2 "general_operand" "g")))]
   ""
-  "jsr %1"
+  "*
+{
+  if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+      && SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+    return \"jsr\\t\@%1:8\";
+  else
+    return \"jsr\\t%1\";
+}"
   [(set_attr "type" "call")
    (set_attr "cc" "clobber")
-   (set_attr "length" "4")])
+   (set (attr "length")
+     (if_then_else (match_operand:QI 0 "small_call_insn_operand" "")
+                  (const_int 4)
+                  (const_int 8)))])
 
 (define_insn "nop"
   [(const_int 0)]