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
This commit is contained in:
Jeff Law 1996-04-01 11:48:52 -07:00
parent eecb6f50c2
commit f5b65a5669
3 changed files with 141 additions and 10 deletions

View 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;
}

View 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). */

View File

@ -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)]