aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1996-04-01 11:48:52 -0700
committerJeff Law <law@gcc.gnu.org>1996-04-01 11:48:52 -0700
commitf5b65a56691fdc8f8b914011da7ed8ec4fa1176c (patch)
tree635a5ec83d2bb80079ecdbc3940f71ca2b73b335
parenteecb6f50c217cb9c7b1442da11309d77771d7162 (diff)
downloadgcc-f5b65a56691fdc8f8b914011da7ed8ec4fa1176c.zip
gcc-f5b65a56691fdc8f8b914011da7ed8ec4fa1176c.tar.gz
gcc-f5b65a56691fdc8f8b914011da7ed8ec4fa1176c.tar.bz2
h8300.c (interrupt_handler): Renamed from pragma_interrupt.
* 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
-rw-r--r--gcc/config/h8300/h8300.c108
-rw-r--r--gcc/config/h8300/h8300.h15
-rw-r--r--gcc/config/h8300/h8300.md28
3 files changed, 141 insertions, 10 deletions
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index cadff01..6a85ecb 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -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;
+}
+
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index b1a44a7..197d814 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -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). */
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index a68d54c..509c960 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -1312,10 +1312,20 @@
[(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).
@@ -1327,10 +1337,20 @@
(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)]