sh.c (SH_ATTRIBUTES): Define.

* config/sh/sh.c (SH_ATTRIBUTES): Define.
	(SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
	(print_operand): Handle resbank in %@ operand code.
	(sh_encode_section_info): New.
	(push_regs): Add conditions for resbank.
	(sh_expand_epilogue): Likewise.
	(sh_insert_attributes): Likewise.
	(sh_attribute_table): Likewise.
	(sh_handle_resbank_handler_attribute): New.
	(sh2a_handle_function_vector_handler_attribute): New.
	(sh2a_is_function_vector_call): New.
	(sh2a_get_function_vector_number): New.
	(sh2a_function_vector_p): New.
	(sh_cfun_resbank_handler_p): New.
	* config/sh/sh.md (calli): Emit jsr/n if possible.
	(calli_tbr_rel): New.
	(calli_pcrel): Emit jsr/n if possible.
	(return_i): Emit rts/n if possible.
	(call_valuei_tbr_rel): New.
	(call_valuei_pcrel): Add condition for SH2A target.
	(call_value): Likewise.
	* config/sh/sh-protos.h (sh_cfun_resbank_handler_p): Declare.
	(sh2a_get_function_vector_number): Likewise.
	(sh2a_is_function_vector_call): Likewise.
	* doc/extend.texi: Document TBR relative addressing of SH2A.
	(resbank): Add description for SH2A.

	* gcc.target/sh/sh2a-resbank.c: New test.
	* gcc.target/sh/sh2a-tbr-jump.c: New test.
	* gcc.target/sh/sh2a-jsrn.c: New test.
	* gcc.target/sh/sh2a-rtsn.c: New test.


Co-Authored-By: Jayant R Sonar <jayant.sonar@kpitcummins.com>
Co-Authored-By: Naveen.H.S <naveen.hs@kpitcummins.com>

From-SVN: r133513
This commit is contained in:
Anil Paranjape 2008-03-25 13:32:13 +00:00 committed by Kaz Kojima
parent 53b308f61e
commit 561642fa67
10 changed files with 454 additions and 17 deletions

View File

@ -1,3 +1,34 @@
2008-03-25 Anil Paranjape <anil.paranjape@kpitcummins.com>
Jayant Sonar <Jayant.sonar@kpitcummins.com>
Naveen.H.S <naveen.hs@kpitcummins.com>
* config/sh/sh.c (SH_ATTRIBUTES): Define.
(SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
(print_operand): Handle resbank in %@ operand code.
(sh_encode_section_info): New.
(push_regs): Add conditions for resbank.
(sh_expand_epilogue): Likewise.
(sh_insert_attributes): Likewise.
(sh_attribute_table): Likewise.
(sh_handle_resbank_handler_attribute): New.
(sh2a_handle_function_vector_handler_attribute): New.
(sh2a_is_function_vector_call): New.
(sh2a_get_function_vector_number): New.
(sh2a_function_vector_p): New.
(sh_cfun_resbank_handler_p): New.
* config/sh/sh.md (calli): Emit jsr/n if possible.
(calli_tbr_rel): New.
(calli_pcrel): Emit jsr/n if possible.
(return_i): Emit rts/n if possible.
(call_valuei_tbr_rel): New.
(call_valuei_pcrel): Add condition for SH2A target.
(call_value): Likewise.
* config/sh/sh-protos.h (sh_cfun_resbank_handler_p): Declare.
(sh2a_get_function_vector_number): Likewise.
(sh2a_is_function_vector_call): Likewise.
* doc/extend.texi: Document TBR relative addressing of SH2A.
(resbank): Add description for SH2A.
2008-03-24 Richard Guenther <rguenther@suse.de>
PR c/22371

View File

@ -134,6 +134,7 @@ extern int initial_elimination_offset (int, int);
extern int fldi_ok (void);
extern int sh_hard_regno_rename_ok (unsigned int, unsigned int);
extern int sh_cfun_interrupt_handler_p (void);
extern int sh_cfun_resbank_handler_p (void);
extern int sh_attr_renesas_p (const_tree);
extern int sh_cfun_attr_renesas_p (void);
extern void sh_initialize_trampoline (rtx, rtx, rtx);
@ -170,6 +171,8 @@ struct secondary_reload_info;
extern enum reg_class sh_secondary_reload (bool, rtx, enum reg_class,
enum machine_mode,
struct secondary_reload_info *);
extern int sh2a_get_function_vector_number (rtx);
extern int sh2a_is_function_vector_call (rtx);
#endif /* ! GCC_SH_PROTOS_H */

View File

@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
#define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))
#define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))
/* Used to simplify the logic below. Find the attributes wherever
they may be. */
#define SH_ATTRIBUTES(decl) \
(TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
: DECL_ATTRIBUTES (decl) \
? (DECL_ATTRIBUTES (decl)) \
: TYPE_ATTRIBUTES (TREE_TYPE (decl))
/* Set to 1 by expand_prologue() when the function is an interrupt handler. */
int current_function_interrupt;
@ -185,6 +193,10 @@ static HOST_WIDE_INT rounded_frame_size (int);
static rtx mark_constant_pool_use (rtx);
const struct attribute_spec sh_attribute_table[];
static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *);
static tree sh_handle_resbank_handler_attribute (tree *, tree,
tree, int, bool *);
static tree sh2a_handle_function_vector_handler_attribute (tree *, tree,
tree, int, bool *);
static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
@ -258,6 +270,8 @@ static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
static bool sh_scalar_mode_supported_p (enum machine_mode);
static int sh_dwarf_calling_convention (const_tree);
static void sh_encode_section_info (tree, rtx, int);
static int sh2a_function_vector_p (tree);
/* Initialize the GCC target structure. */
@ -449,6 +463,9 @@ static int sh_dwarf_calling_convention (const_tree);
/* Return current register pressure for regmode. */
#define CURR_REGMODE_PRESSURE(MODE) curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO sh_encode_section_info
#ifdef SYMBIAN
#undef TARGET_ENCODE_SECTION_INFO
@ -463,6 +480,9 @@ static int sh_dwarf_calling_convention (const_tree);
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD sh_secondary_reload
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
struct gcc_target targetm = TARGET_INITIALIZER;
/* Implement TARGET_HANDLE_OPTION. */
@ -690,7 +710,11 @@ print_operand (FILE *stream, rtx x, int code)
fprintf (stream, "trapa #%ld",
(long) TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (trapa_attr))));
else if (sh_cfun_interrupt_handler_p ())
fprintf (stream, "rte");
{
if (sh_cfun_resbank_handler_p ())
fprintf (stream, "resbank\n");
fprintf (stream, "rte");
}
else
fprintf (stream, "rts");
break;
@ -1022,6 +1046,19 @@ print_operand (FILE *stream, rtx x, int code)
}
}
/* Encode symbol attributes of a SYMBOL_REF into its
SYMBOL_REF_FLAGS. */
static void
sh_encode_section_info (tree decl, rtx rtl, int first)
{
default_encode_section_info (decl, rtl, first);
if (TREE_CODE (decl) == FUNCTION_DECL
&& sh2a_function_vector_p (decl) && TARGET_SH2A)
SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FUNCVEC_FUNCTION;
}
/* Like force_operand, but guarantees that VALUE ends up in TARGET. */
static void
force_into (rtx value, rtx target)
@ -5767,7 +5804,16 @@ push_regs (HARD_REG_SET *mask, int interrupt_handler)
if (i != PR_REG
&& (i != FPSCR_REG || ! skip_fpscr)
&& TEST_HARD_REG_BIT (*mask, i))
push (i);
{
/* If the ISR has RESBANK attribute assigned, don't push any of
the following registers - R0-R14, MACH, MACL and GBR. */
if (! (sh_cfun_resbank_handler_p ()
&& ((i >= FIRST_GENERAL_REG && i < LAST_GENERAL_REG)
|| i == MACH_REG
|| i == MACL_REG
|| i == GBR_REG)))
push (i);
}
}
/* Push banked registers last to improve delay slot opportunities. */
@ -5776,7 +5822,8 @@ push_regs (HARD_REG_SET *mask, int interrupt_handler)
if (TEST_HARD_REG_BIT (*mask, i))
push (i);
if (TEST_HARD_REG_BIT (*mask, PR_REG))
/* Don't push PR register for an ISR with RESBANK attribute assigned. */
if (TEST_HARD_REG_BIT (*mask, PR_REG) && !sh_cfun_resbank_handler_p ())
push (PR_REG);
}
@ -6705,7 +6752,10 @@ sh_expand_epilogue (bool sibcall_p)
int last_reg;
save_size = 0;
if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
/* For an ISR with RESBANK attribute assigned, don't pop PR
register. */
if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG)
&& !sh_cfun_resbank_handler_p ())
{
if (!frame_pointer_needed)
emit_insn (gen_blockage ());
@ -6733,7 +6783,15 @@ sh_expand_epilogue (bool sibcall_p)
&& hard_reg_set_intersect_p (live_regs_mask,
reg_class_contents[DF_REGS]))
fpscr_deferred = 1;
else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j))
/* For an ISR with RESBANK attribute assigned, don't pop
following registers, R0-R14, MACH, MACL and GBR. */
else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j)
&& ! (sh_cfun_resbank_handler_p ()
&& ((j >= FIRST_GENERAL_REG
&& j < LAST_GENERAL_REG)
|| j == MACH_REG
|| j == MACL_REG
|| j == GBR_REG)))
pop (j);
if (j == FIRST_FP_REG && fpscr_deferred)
@ -7904,11 +7962,13 @@ sh_insert_attributes (tree node, tree *attributes)
java frontend. */
attrs
= tree_cons (get_identifier("interrupt_handler"), NULL_TREE, attrs);
/* However, for sp_switch, trap_exit and nosave_low_regs, if the
interrupt attribute is missing, we ignore the attribute and warn. */
/* However, for sp_switch, trap_exit, nosave_low_regs and resbank,
if the interrupt attribute is missing, we ignore the attribute
and warn. */
else if (lookup_attribute ("sp_switch", attrs)
|| lookup_attribute ("trap_exit", attrs)
|| lookup_attribute ("nosave_low_regs", attrs))
|| lookup_attribute ("nosave_low_regs", attrs)
|| lookup_attribute ("resbank", attrs))
{
tree *tail;
@ -7916,7 +7976,8 @@ sh_insert_attributes (tree node, tree *attributes)
{
if (is_attribute_p ("sp_switch", TREE_PURPOSE (attrs))
|| is_attribute_p ("trap_exit", TREE_PURPOSE (attrs))
|| is_attribute_p ("nosave_low_regs", TREE_PURPOSE (attrs)))
|| is_attribute_p ("nosave_low_regs", TREE_PURPOSE (attrs))
|| is_attribute_p ("resbank", TREE_PURPOSE (attrs)))
warning (OPT_Wattributes,
"%qs attribute only applies to interrupt functions",
IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
@ -7963,6 +8024,8 @@ sh_insert_attributes (tree node, tree *attributes)
renesas -- use Renesas calling/layout conventions (functions and
structures).
resbank -- In case of an ISR, use a register bank to save registers
R0-R14, MACH, MACL, GBR and PR. This is useful only on SH2A targets.
*/
const struct attribute_spec sh_attribute_table[] =
@ -7974,6 +8037,8 @@ const struct attribute_spec sh_attribute_table[] =
{ "renesas", 0, 0, false, true, false, sh_handle_renesas_attribute },
{ "trapa_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
{ "nosave_low_regs", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
{ "resbank", 0, 0, true, false, false, sh_handle_resbank_handler_attribute },
{ "function_vector", 1, 1, true, false, false, sh2a_handle_function_vector_handler_attribute },
#ifdef SYMBIAN
/* Symbian support adds three new attributes:
dllexport - for exporting a function/variable that will live in a dll
@ -7988,18 +8053,41 @@ const struct attribute_spec sh_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL }
};
/* Handle a 'resbank' attribute. */
static tree
sh_handle_resbank_handler_attribute (tree * node, tree name,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool * no_add_attrs)
{
if (!TARGET_SH2A)
{
warning (OPT_Wattributes, "%qs attribute is supported only for SH2A",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return NULL_TREE;
}
/* Handle an "interrupt_handler" attribute; arguments as in
struct attribute_spec.handler. */
static tree
sh_handle_interrupt_handler_attribute (tree *node, tree name,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
else if (TARGET_SHCOMPACT)
@ -8011,6 +8099,96 @@ sh_handle_interrupt_handler_attribute (tree *node, tree name,
return NULL_TREE;
}
/* Handle an 'function_vector' attribute; arguments as in
struct attribute_spec.handler. */
static tree
sh2a_handle_function_vector_handler_attribute (tree * node, tree name,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool * no_add_attrs)
{
if (!TARGET_SH2A)
{
warning (OPT_Wattributes, "%qs attribute only applies to SH2A",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
else if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
{
/* The argument must be a constant integer. */
warning (OPT_Wattributes,
"`%s' attribute argument not an integer constant",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
else if (TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
{
/* The argument value must be between 0 to 255. */
warning (OPT_Wattributes,
"`%s' attribute argument should be between 0 to 255",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return NULL_TREE;
}
/* Returns 1 if current function has been assigned the attribute
'function_vector'. */
int
sh2a_is_function_vector_call (rtx x)
{
if (GET_CODE (x) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
{
tree tr = SYMBOL_REF_DECL (x);
if (sh2a_function_vector_p (tr))
return 1;
}
return 0;
}
/* Returns the function vector number, if the the attribute
'function_vector' is assigned, otherwise returns zero. */
int
sh2a_get_function_vector_number (rtx x)
{
int num;
tree list, t;
if ((GET_CODE (x) == SYMBOL_REF)
&& (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
{
t = SYMBOL_REF_DECL (x);
if (TREE_CODE (t) != FUNCTION_DECL)
return 0;
list = SH_ATTRIBUTES (t);
while (list)
{
if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
{
num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
return num;
}
list = TREE_CHAIN (list);
}
return 0;
}
else
return 0;
}
/* Handle an "sp_switch" attribute; arguments as in
struct attribute_spec.handler. */
static tree
@ -8101,6 +8279,39 @@ sh_cfun_interrupt_handler_p (void)
!= NULL_TREE);
}
/* Returns 1 if FUNC has been assigned the attribute
"function_vector". */
int
sh2a_function_vector_p (tree func)
{
tree list;
if (TREE_CODE (func) != FUNCTION_DECL)
return 0;
list = SH_ATTRIBUTES (func);
while (list)
{
if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
return 1;
list = TREE_CHAIN (list);
}
return 0;
}
/* Returns TRUE if given tree has the "resbank" attribute. */
int
sh_cfun_resbank_handler_p (void)
{
return ((lookup_attribute ("resbank",
DECL_ATTRIBUTES (current_function_decl))
!= NULL_TREE)
&& (lookup_attribute ("interrupt_handler",
DECL_ATTRIBUTES (current_function_decl))
!= NULL_TREE) && TARGET_SH2A);
}
/* Implement TARGET_CHECK_PCH_TARGET_FLAGS. */
static const char *

View File

@ -7443,7 +7443,14 @@ label:
(use (reg:PSI FPSCR_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH1"
"jsr @%0%#"
"*
{
if (TARGET_SH2A && (dbr_sequence_length () == 0))
return \"jsr/n\\t@%0\";
else
return \"jsr\\t@%0%#\";
}"
[(set_attr "type" "call")
(set (attr "fp_mode")
(if_then_else (eq_attr "fpu_single" "yes")
@ -7451,6 +7458,31 @@ label:
(set_attr "needs_delay_slot" "yes")
(set_attr "fp_set" "unknown")])
;; This is TBR relative jump instruction for SH2A architecture.
;; Its use is enabled assigning an attribute "function_vector"
;; and the vector number to a function during its declaration.
(define_insn "calli_tbr_rel"
[(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
(match_operand 1 "" ""))
(use (reg:PSI FPSCR_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
"*
{
unsigned HOST_WIDE_INT vect_num;
vect_num = sh2a_get_function_vector_number (operands[0]);
operands[2] = GEN_INT (vect_num * 4);
return \"jsr/n\\t@@(%O2,tbr)\";
}"
[(set_attr "type" "call")
(set (attr "fp_mode")
(if_then_else (eq_attr "fpu_single" "yes")
(const_string "single") (const_string "double")))
(set_attr "needs_delay_slot" "no")
(set_attr "fp_set" "unknown")])
;; This is a pc-rel call, using bsrf, for use with PIC.
(define_insn "calli_pcrel"
@ -7546,7 +7578,13 @@ label:
(use (reg:PSI FPSCR_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH1"
"jsr @%1%#"
"*
{
if (TARGET_SH2A && (dbr_sequence_length () == 0))
return \"jsr/n\\t@%1\";
else
return \"jsr\\t@%1%#\";
}"
[(set_attr "type" "call")
(set (attr "fp_mode")
(if_then_else (eq_attr "fpu_single" "yes")
@ -7554,6 +7592,32 @@ label:
(set_attr "needs_delay_slot" "yes")
(set_attr "fp_set" "unknown")])
;; This is TBR relative jump instruction for SH2A architecture.
;; Its use is enabled assigning an attribute "function_vector"
;; and the vector number to a function during its declaration.
(define_insn "call_valuei_tbr_rel"
[(set (match_operand 0 "" "=rf")
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
(match_operand 2 "" "")))
(use (reg:PSI FPSCR_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
"*
{
unsigned HOST_WIDE_INT vect_num;
vect_num = sh2a_get_function_vector_number (operands[1]);
operands[3] = GEN_INT (vect_num * 4);
return \"jsr/n\\t@@(%O3,tbr)\";
}"
[(set_attr "type" "call")
(set (attr "fp_mode")
(if_then_else (eq_attr "fpu_single" "yes")
(const_string "single") (const_string "double")))
(set_attr "needs_delay_slot" "no")
(set_attr "fp_set" "unknown")])
(define_insn "call_valuei_pcrel"
[(set (match_operand 0 "" "=rf")
(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
@ -7715,6 +7779,17 @@ label:
emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
XEXP (operands[0], 0) = reg;
}
if (!flag_pic && TARGET_SH2A
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
{
if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
{
emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0),
operands[1]));
DONE;
}
}
if (flag_pic && TARGET_SH2
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
@ -7898,6 +7973,17 @@ label:
emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
XEXP (operands[1], 0) = reg;
}
if (!flag_pic && TARGET_SH2A
&& GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
{
if (sh2a_is_function_vector_call (XEXP (operands[1], 0)))
{
emit_call_insn (gen_call_valuei_tbr_rel (operands[0],
XEXP (operands[1], 0), operands[2]));
DONE;
}
}
if (flag_pic && TARGET_SH2
&& GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
@ -9262,7 +9348,14 @@ mov.l\\t1f,r0\\n\\
&& reload_completed
&& lookup_attribute (\"trap_exit\",
DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
"%@ %#"
"*
{
if (TARGET_SH2A && (dbr_sequence_length () == 0)
&& !current_function_interrupt)
return \"rts/n\";
else
return \"%@ %#\";
}"
[(set_attr "type" "return")
(set_attr "needs_delay_slot" "yes")])

View File

@ -2299,16 +2299,33 @@ is used. @xref{C Dialect Options,,Options
Controlling C Dialect}.
@item function_vector
@cindex calling functions through the function vector on H8/300, M16C, and M32C processors
@cindex calling functions through the function vector on H8/300, M16C, M32C and SH2A processors
Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
function should be called through the function vector. Calling a
function through the function vector will reduce code size, however;
the function vector has a limited size (maximum 128 entries on the H8/300
and 64 entries on the H8/300H and H8S) and shares space with the interrupt vector.
In SH2A target, this attribute declares a function to be called using the
TBR relative addressing mode. The argument to this attribute is the entry
number of the same function in a vector table containing all the TBR
relative addressable functions. For the successful jump, register TBR
should contain the start address of this TBR relative vector table.
In the startup routine of the user application, user needs to care of this
TBR register initialization. The TBR relative vector table can have at
max 256 function entries. The jumps to these functions will be generated
using a SH2A specific, non delayed branch instruction JSR/N @@(disp8,TBR).
You must use GAS and GLD from GNU binutils version 2.7 or later for
this attribute to work correctly.
Please refer the example of M16C target, to see the use of this
attribute while declaring a function,
In an application, for a function being called once, this attribute will
save at least 8 bytes of code; and if other successive calls are being
made to the same function, it will save 2 bytes of code per each of these
calls.
On M16C/M32C targets, the @code{function_vector} attribute declares a
special page subroutine call function. Use of this attribute reduces
the code size by 2 bytes for each call generated to the
@ -2722,6 +2739,19 @@ number of registers available if used in conjunction with the
attribute is incompatible with nested functions; this is considered a
hard error.
@item resbank
@cindex @code{resbank} attribute
On the SH2A target, this attribute enables the high-speed register
saving and restoration using a register bank for @code{interrupt_handler}
routines. Saving to the bank is performed automatcially after the CPU
accepts an interrupt that uses a register bank.
The nineteen 32-bit registers comprising general register R0 to R14,
control register GBR, and system registers MACH, MACL, and PR and the
vector table address offset are saved into a register bank. Register
banks are stacked in first-in last-out (FILO) sequence. Restoration
from the bank is executed by issuing a RESBANK instruction.
@item returns_twice
@cindex @code{returns_twice} attribute
The @code{returns_twice} attribute tells the compiler that a function may

View File

@ -1,3 +1,12 @@
2008-03-25 Anil Paranjape <anil.paranjape@kpitcummins.com>
Jayant Sonar <Jayant.sonar@kpitcummins.com>
Naveen.H.S <naveen.hs@kpitcummins.com>
* gcc.target/sh/sh2a-resbank.c: New test.
* gcc.target/sh/sh2a-tbr-jump.c: New test.
* gcc.target/sh/sh2a-jsrn.c: New test.
* gcc.target/sh/sh2a-rtsn.c: New test.
2008-03-25 Uros Bizjak <ubizjak@gmail.com>
* gcc.target/i386/sse-17.c: Include sse2-check.h.

View File

@ -0,0 +1,15 @@
/* Testcase to check generation of a SH2A specific instruction for
'JSR/N @Rm'. */
/* { dg-do assemble {target sh*-*-*}} */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "jsr/n"} } */
void foo(void)
{
}
void bar()
{
foo();
}

View File

@ -0,0 +1,12 @@
/* Test for resbank attribute. */
/* { dg-do assemble {target sh*-*-*}} */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "resbank" } } */
extern void bar(void);
void foo(void) __attribute__((interrupt_handler, resbank));
void foo(void)
{
bar();
}

View File

@ -0,0 +1,11 @@
/* Testcase to check generation of a SH2A specific instruction for
'RTS/N'. */
/* { dg-do assemble {target sh*-*-*}} */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "rts/n"} } */
void
bar (void)
{
}

View File

@ -0,0 +1,22 @@
/* Testcase to check generation of a SH2A specific,
TBR relative jump instruction - 'JSR @@(disp8,TBR)'. */
/* { dg-do assemble {target sh*-*-*}} */
/* { dg-options "" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler-times "jsr/n\\t@@\\(40,tbr\\)" 1} } */
/* { dg-final { scan-assembler-times "jsr/n\\t@@\\(72,tbr\\)" 1} } */
extern void foo1 (void) __attribute__ ((function_vector(10)));
extern void foo2 (void);
extern int bar1 (void) __attribute__ ((function_vector(18)));
extern int bar2 (void);
int
bar()
{
foo1();
foo2();
bar1();
bar2();
}