diff options
author | Anil Paranjape <anil.paranjape@kpitcummins.com> | 2008-03-25 13:32:13 +0000 |
---|---|---|
committer | Kaz Kojima <kkojima@gcc.gnu.org> | 2008-03-25 13:32:13 +0000 |
commit | 561642fa67798158762265f5100e3052275fe970 (patch) | |
tree | 9d545fbf7312945f348908340895704e9ccd4110 /gcc | |
parent | 53b308f61e96c47b54abf5c7db2e9831cbc43e66 (diff) | |
download | gcc-561642fa67798158762265f5100e3052275fe970.zip gcc-561642fa67798158762265f5100e3052275fe970.tar.gz gcc-561642fa67798158762265f5100e3052275fe970.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 237 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 99 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/sh2a-jsrn.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/sh2a-resbank.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/sh2a-rtsn.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c | 22 |
10 files changed, 454 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a1ab328..071d094 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 25d9ce4..9e1a488 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -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 */ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index b43033b..57049ea 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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 * diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 5a580b5..6dae438 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -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")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index b28d9df..1fa7fc2 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 68ba56b..103aaf2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c b/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c new file mode 100644 index 0000000..9b9b92c --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c @@ -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(); +} diff --git a/gcc/testsuite/gcc.target/sh/sh2a-resbank.c b/gcc/testsuite/gcc.target/sh/sh2a-resbank.c new file mode 100644 index 0000000..aab6852 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/sh2a-resbank.c @@ -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(); +} diff --git a/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c b/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c new file mode 100644 index 0000000..2601ced --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c @@ -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) +{ +} diff --git a/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c b/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c new file mode 100644 index 0000000..8029b03 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c @@ -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(); +} |