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:
parent
eecb6f50c2
commit
f5b65a5669
|
@ -40,11 +40,16 @@ Boston, MA 02111-1307, USA. */
|
||||||
void print_operand_address ();
|
void print_operand_address ();
|
||||||
char *index ();
|
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. */
|
/* CPU_TYPE, says what cpu we're compiling for. */
|
||||||
int cpu_type;
|
int cpu_type;
|
||||||
|
|
||||||
/* True if a #pragma interrupt has been seen for the current function. */
|
/* True if the current function is an interrupt handler
|
||||||
int pragma_interrupt;
|
(either via #pragma or an attribute specification). */
|
||||||
|
int interrupt_handler;
|
||||||
|
|
||||||
|
|
||||||
/* True if a #pragma saveall has been seen for the current function. */
|
/* True if a #pragma saveall has been seen for the current function. */
|
||||||
int pragma_saveall;
|
int pragma_saveall;
|
||||||
|
@ -110,7 +115,7 @@ byte_reg (x, b)
|
||||||
|
|
||||||
#define WORD_REG_USED(regno) \
|
#define WORD_REG_USED(regno) \
|
||||||
(regno < 7 && \
|
(regno < 7 && \
|
||||||
(pragma_interrupt \
|
(interrupt_handler \
|
||||||
|| pragma_saveall \
|
|| pragma_saveall \
|
||||||
|| (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
|
|| (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
|
||||||
|| (regs_ever_live[regno] & !call_used_regs[regno])))
|
|| (regs_ever_live[regno] & !call_used_regs[regno])))
|
||||||
|
@ -190,6 +195,9 @@ function_prologue (file, size)
|
||||||
int idx;
|
int idx;
|
||||||
extra_pop = 0;
|
extra_pop = 0;
|
||||||
|
|
||||||
|
if (h8300_interrupt_function_p (current_function_decl))
|
||||||
|
interrupt_handler = 1;
|
||||||
|
|
||||||
if (current_function_anonymous_args && TARGET_QUICKCALL)
|
if (current_function_anonymous_args && TARGET_QUICKCALL)
|
||||||
{
|
{
|
||||||
/* Push regs as if done by caller, and move around return address. */
|
/* Push regs as if done by caller, and move around return address. */
|
||||||
|
@ -325,13 +333,13 @@ function_epilogue (file, size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pragma_interrupt)
|
if (interrupt_handler)
|
||||||
fprintf (file, "\trte\n");
|
fprintf (file, "\trte\n");
|
||||||
else
|
else
|
||||||
fprintf (file, "\trts\n");
|
fprintf (file, "\trts\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma_interrupt = 0;
|
interrupt_handler = 0;
|
||||||
pragma_saveall = 0;
|
pragma_saveall = 0;
|
||||||
|
|
||||||
current_function_anonymous_args = 0;
|
current_function_anonymous_args = 0;
|
||||||
|
@ -470,6 +478,32 @@ call_insn_operand (op, mode)
|
||||||
return 0;
|
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. */
|
/* Return true if OP is a valid jump operand. */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -569,7 +603,7 @@ handle_pragma (file, c)
|
||||||
pbuf[psize] = 0;
|
pbuf[psize] = 0;
|
||||||
|
|
||||||
if (strcmp (pbuf, "interrupt") == 0)
|
if (strcmp (pbuf, "interrupt") == 0)
|
||||||
pragma_interrupt = 1;
|
interrupt_handler = 1;
|
||||||
else if (strcmp (pbuf, "saveall") == 0)
|
else if (strcmp (pbuf, "saveall") == 0)
|
||||||
pragma_saveall = 1;
|
pragma_saveall = 1;
|
||||||
|
|
||||||
|
@ -2065,3 +2099,65 @@ fix_bit_operand (operands, what, type)
|
||||||
}
|
}
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -932,6 +932,13 @@ extern int current_function_anonymous_args;
|
||||||
so give the MEM rtx a byte's mode. */
|
so give the MEM rtx a byte's mode. */
|
||||||
#define FUNCTION_MODE QImode
|
#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
|
/* Compute the cost of computing a constant rtl expression RTX
|
||||||
whose rtx-code is CODE. The body of this macro is a portion
|
whose rtx-code is CODE. The body of this macro is a portion
|
||||||
of a switch statement. If the code is computed here,
|
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.
|
/* How to refer to registers in assembler output.
|
||||||
This sequence is indexed by compiler's hard-register-number (see above). */
|
This sequence is indexed by compiler's hard-register-number (see above). */
|
||||||
|
|
||||||
|
|
|
@ -1312,10 +1312,20 @@
|
||||||
[(call (match_operand:QI 0 "call_insn_operand" "or")
|
[(call (match_operand:QI 0 "call_insn_operand" "or")
|
||||||
(match_operand:HI 1 "general_operand" "g"))]
|
(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 "type" "call")
|
||||||
(set_attr "cc" "clobber")
|
(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
|
;; Call subroutine, returning value in operand 0
|
||||||
;; (which must be a hard register).
|
;; (which must be a hard register).
|
||||||
|
@ -1327,10 +1337,20 @@
|
||||||
(call (match_operand:QI 1 "call_insn_operand" "or")
|
(call (match_operand:QI 1 "call_insn_operand" "or")
|
||||||
(match_operand:HI 2 "general_operand" "g")))]
|
(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 "type" "call")
|
||||||
(set_attr "cc" "clobber")
|
(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"
|
(define_insn "nop"
|
||||||
[(const_int 0)]
|
[(const_int 0)]
|
||||||
|
|
Loading…
Reference in New Issue