public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH,SH] Add SH2A new instructions 1/6
@ 2007-10-25 12:15 Naveen H.S.
  2007-10-29  1:34 ` Kaz Kojima
  0 siblings, 1 reply; 8+ messages in thread
From: Naveen H.S. @ 2007-10-25 12:15 UTC (permalink / raw)
  To: Kaz Kojima; +Cc: gcc-patches, Anil Paranjape, Prafulla Thakare

[-- Attachment #1: Type: text/plain, Size: 2337 bytes --]

Hi,

>> check once more our coding standard.
Thank you for the valuable comments. We have taken care of the
comments in the modified patch. 

Please find attached the patch "sh2a1.patch". This patch implements new
instructions RTS/N, JSR/N, JSR/N @@ and RESBANK for SH2A target.

No new regressions.

ChangeLog
2007-10-18	Anil Paranjape <anil.paranjape@kpitcummins.com>
          	Jayant Sonar <Jayant.sonar@kpitcummins.com>
          	            
	* config/sh/sh.c (SH_ATTRIBUTES): Define.
	(SYMBOL_FLAG_FUNCVEC_FUNCTION): Define.
	(print_operand): "@" prints resbank if the instruction RESBANK 
	has to be generated.
	(sh_encode_section_info): New.
	(push_regs): Add conditions for resbank.
	(sh_expand_epilogue): Add conditions for resbank.
	(sh_insert_attributes): Add resbank attribute.
	(sh_attribute_table): Add resbank and function_vector
	attributes.
	(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): Add JSR/N instruction if the
	instruction does not have delay slot.
	(calli_tbr_rel): New.
	(calli_pcrel): Add JSR/N instruction if the instruction does 
	not have delay slot.
	(return_i): Add RTS/N instruction if the instruction does not
	have delay slot.
	(call_valuei_tbr_rel): New.
	(call_valuei_pcrel): Add condition for SH2A target.
	(call_value): Add condition for SH2A target.
	* config/sh/sh-protos.h : Update as needed.
	* doc/extend.texi (TBR relative addressing): Added description 
	for SH2A target.
	(resbank): Added description for SH2A target.
	* testsuite/gcc.target/sh/sh2a-resbank.c : New.
	* testsuite/gcc.target/sh/sh2a-tbr-jump.c: New.

Regards,
Naveen.H.S.
KPIT Cummins Infosystems Ltd,
Pune (INDIA) 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
Free download of GNU based tool-chains for Renesas' SH, H8, R8C, M16C	
and M32C Series. The following site also offers free technical support	
to its users. Visit http://www.kpitgnutools.com for details. 	
Latest versions of KPIT GNU tools were released on October 1, 2007.	
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

[-- Attachment #2: sh2a1.patch --]
[-- Type: application/octet-stream, Size: 24902 bytes --]

diff -upr gcc-4.3-20070921/gcc/config/sh/sh.c tars/gcc-4.3-20070921/gcc/config/sh/sh.c
--- gcc-4.3-20070921/gcc/config/sh/sh.c	2007-09-19 20:33:07.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/config/sh/sh.c	2007-10-24 11:48:18.000000000 +0530
@@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = COD
 #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 
 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 *);
@@ -256,6 +268,9 @@ static bool sh_callee_copies (CUMULATIVE
 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 			         tree, bool);
 static int sh_dwarf_calling_convention (const_tree);
+static void sh_encode_section_info (tree, rtx, int);
+static int sh2a_function_vector_p (tree);
+
 
 \f
 /* Initialize the GCC target structure.  */
@@ -443,6 +458,9 @@ static int sh_dwarf_calling_convention (
 /* 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
@@ -457,6 +475,9 @@ static int sh_dwarf_calling_convention (
 #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;
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -684,7 +705,12 @@ print_operand (FILE *stream, rtx x, int 
 	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;
@@ -1016,6 +1042,25 @@ print_operand (FILE *stream, rtx x, int 
     }
 }
 \f
+
+/* Encode symbol attributes of a SYMBOL_REF into its
+   SYMBOL_REF_FLAGS.  */
+static void
+sh_encode_section_info (tree decl, rtx rtl, int first)
+{
+  int extra_flags = 0;
+
+  default_encode_section_info (decl, rtl, first);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && sh2a_function_vector_p (decl)
+      && TARGET_SH2A)
+    extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
+
+  if (extra_flags)
+    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
+}
+
 /* Like force_operand, but guarantees that VALUE ends up in TARGET.  */
 static void
 force_into (rtx value, rtx target)
@@ -5750,7 +5795,16 @@ push_regs (HARD_REG_SET *mask, int inter
       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
+   	   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.  */
@@ -5759,7 +5813,8 @@ push_regs (HARD_REG_SET *mask, int inter
       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);
 }
 
@@ -6688,7 +6743,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 ());
@@ -6716,7 +6774,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)
@@ -7887,11 +7953,13 @@ sh_insert_attributes (tree node, tree *a
 	   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;
 
@@ -7899,7 +7967,8 @@ sh_insert_attributes (tree node, tree *a
 	    {
 	      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)));
@@ -7946,6 +8015,8 @@ sh_insert_attributes (tree node, tree *a
    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[] =
@@ -7957,6 +8028,8 @@ const struct attribute_spec sh_attribute
   { "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
@@ -7971,6 +8044,29 @@ const struct attribute_spec sh_attribute
   { 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
@@ -7994,6 +8090,97 @@ sh_handle_interrupt_handler_attribute (t
   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
@@ -8084,6 +8271,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 -upr gcc-4.3-20070921/gcc/config/sh/sh.md tars/gcc-4.3-20070921/gcc/config/sh/sh.md
--- gcc-4.3-20070921/gcc/config/sh/sh.md	2007-09-12 09:16:53.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/config/sh/sh.md	2007-10-24 12:00:23.000000000 +0530
@@ -7437,7 +7437,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")
@@ -7445,6 +7452,30 @@ 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 = 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"
@@ -7540,7 +7571,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")
@@ -7548,6 +7585,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 TBR_REG))
+   (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 = 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"))
@@ -7709,6 +7772,16 @@ 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)
@@ -7892,6 +7965,16 @@ 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)
@@ -9256,7 +9339,13 @@ 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 -upr gcc-4.3-20070921/gcc/config/sh/sh-protos.h tars/gcc-4.3-20070921/gcc/config/sh/sh-protos.h
--- gcc-4.3-20070921/gcc/config/sh/sh-protos.h	2007-08-23 21:19:56.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/config/sh/sh-protos.h	2007-10-24 11:48:18.000000000 +0530
@@ -137,6 +137,7 @@ extern int initial_elimination_offset (i
 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);
@@ -173,6 +174,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 */
 
--- gcc-4.3-20070921/gcc/doc/extend.texi	2007-09-20 21:25:33.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/doc/extend.texi	2007-10-24 11:48:18.000000000 +0530
@@ -2248,13 +2248,31 @@ is used.  @xref{C Dialect Options,,Optio
 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).
+
+Please refer the above 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.
+
 You must use GAS and GLD from GNU binutils version 2.7 or later for
 this attribute to work correctly.
 
@@ -2660,6 +2678,19 @@ number of registers available if used in
 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 -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c
--- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	1970-01-01 05:30:00.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	2007-10-24 11:55:53.000000000 +0530
@@ -0,0 +1,17 @@
+/* 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 -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c
--- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c	1970-01-01 05:30:00.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c	2007-10-24 11:48:18.000000000 +0530
@@ -0,0 +1,14 @@
+ /* 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 -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c
--- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	1970-01-01 05:30:00.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	2007-10-24 12:03:50.000000000 +0530
@@ -0,0 +1,13 @@
+/* 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 -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c
--- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	1970-01-01 05:30:00.000000000 +0530
+++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	2007-10-24 11:48:18.000000000 +0530
@@ -0,0 +1,25 @@
+/* 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\\t@r\[0-9\]" 2} } */
+/* { 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();
+}
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,SH] Add SH2A new instructions 1/6
  2007-10-25 12:15 [PATCH,SH] Add SH2A new instructions 1/6 Naveen H.S.
@ 2007-10-29  1:34 ` Kaz Kojima
  0 siblings, 0 replies; 8+ messages in thread
From: Kaz Kojima @ 2007-10-29  1:34 UTC (permalink / raw)
  To: naveen.hs; +Cc: gcc-patches, Anil.Paranjape, Prafulla.Thakare

"Naveen H.S." <naveen.hs@kpitcummins.com> wrote:
>>> check once more our coding standard.
> Thank you for the valuable comments. We have taken care of the
> comments in the modified patch. 
>
> Please find attached the patch "sh2a1.patch". This patch implements new
> instructions RTS/N, JSR/N, JSR/N @@ and RESBANK for SH2A target.

Patch looks Ok logically, but there are still many issues about
coding standard.  Check once more our coding standard, carefully.

> No new regressions.

Please describe how the patch was tested more explicitly next time.
Did you run C and C++ testsuite with all -m2a* -ml/mb combinations?
You should refer about make dvi, make info and make pdf because
you touch a doc file.

Here is a list of the coding standard issues I've found, though
there may be more.  Please find and fix them yourself and re-post
the revised patch when the trunk returns to stage1.

> --- gcc-4.3-20070921/gcc/config/sh/sh.c	2007-09-19 20:33:07.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/config/sh/sh.c	2007-10-24 11:48:18.000000000 +0530
> @@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = COD
>  #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))
   ^^^^^^^^^^^^^^^^
Use tabs.

> +static tree sh_handle_resbank_handler_attribute (tree *, tree, 
                                                                 ^
Extra trailing space.

> +static int sh2a_function_vector_p (tree);
> +
>  
>  \f

Don't add an extra empty line here.

> @@ -1016,6 +1042,25 @@ print_operand (FILE *stream, rtx x, int 
>      }
>  }
>  \f
> +
> +/* Encode symbol attributes of a SYMBOL_REF into its
> +   SYMBOL_REF_FLAGS.  */
> +static void
> +sh_encode_section_info (tree decl, rtx rtl, int first)
> +{
> +  int extra_flags = 0;
> +
> +  default_encode_section_info (decl, rtl, first);
> +
> +  if (TREE_CODE (decl) == FUNCTION_DECL
> +      && sh2a_function_vector_p (decl)
> +      && TARGET_SH2A)
> +    extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
> +
> +  if (extra_flags)
> +    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
> +}

It looks that you don't need extra_flags variable:

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

> @@ -5750,7 +5795,16 @@ push_regs (HARD_REG_SET *mask, int inter
[snip]
>        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
> +   	   the following registers - R0-R14, MACH, MACL and GBR.  */

The last 3 lines have still wrong indentations.  Extra "the".
Should be

	{
	  /* 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)))
    ^^^^^^^^^^^^^^^^
Use tabs.

> @@ -5759,7 +5813,8 @@ push_regs (HARD_REG_SET *mask, int inter
>        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 ()))

Remove () around sh_cfun_resbank_handler_p ().

>  }
>  
> @@ -6688,7 +6743,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.  */
   ^^^^^^^^
Use a tab.

> +      if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG)
> +          && !(sh_cfun_resbank_handler_p ()))	
   ^^^^^^^^
Same here.  Remove () around sh_cfun_resbank_handler_p ().

> @@ -6716,7 +6774,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)))
   ^^^^^^^^^^^^^^^^^^^^^^^^
Use tabs.  Wrong indentations at the last 3 lines.
Also many extra trailing spaces.

> @@ -7946,6 +8015,8 @@ sh_insert_attributes (tree node, tree *a
>     renesas -- use Renesas calling/layout conventions (functions and
>     structures).
>  
> +   resbank -- In case of an ISR, use a register bank to save registers 
                                                                         ^
Extra trailing space.

> +   R0-R14, MACH, MACL, GBR and PR. This is useful only on SH2A targets.
                                     ^^ 2 spaces are needed.

> +/* Handle a "resbank" attribute  */

Missing period.

> +static tree
> +sh_handle_resbank_handler_attribute (tree *node, tree name,
> +                                     tree args ATTRIBUTE_UNUSED,
> +                                     int flags ATTRIBUTE_UNUSED,
> +                                     bool *no_add_attrs)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use tabs.

> +      warning (OPT_Wattributes, "%qs attribute is supported only for SH2A",
> +               IDENTIFIER_POINTER (name));
   ^^^^^^^^
Same here

> +      warning (OPT_Wattributes, "%qs attribute only applies to functions",
> +               IDENTIFIER_POINTER (name));
   ^^^^^^^^
and here.

> +static tree
> +sh2a_handle_function_vector_handler_attribute (tree *node, tree name,
> +                                               tree args ATTRIBUTE_UNUSED,
> +                                               int flags ATTRIBUTE_UNUSED,
> +                                               bool *no_add_attrs)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use tabs.

> +      warning (OPT_Wattributes, "%qs attribute only applies to SH2A",
> +               IDENTIFIER_POINTER (name));
[snip]
> +      warning (OPT_Wattributes, "%qs attribute only applies to functions",
> +               IDENTIFIER_POINTER (name));
[snip]
> +      warning (OPT_Wattributes,
> +               "`%s' attribute argument not an integer constant",
> +               IDENTIFIER_POINTER (name));
[snip]
> +      warning (OPT_Wattributes,
> +               "`%s' attribute argument should be between 0 to 255",
> +               IDENTIFIER_POINTER (name));
   ^^^^^^^^
Another examples.

> +/* Returns 1 if current function has been assigned the attribute
> +   "function_vector"  */

Missing period.

> +sh2a_is_function_vector_call (rtx x)
[snip]
> +      if (sh2a_function_vector_p (tr))
> +        return 1;
   ^^^^^^^^
Use a tab.

> +/* Returns the function vector number, if the the attribute 
                                                              ^
Extra trailing space.

> +sh2a_get_function_vector_number (rtx x)
> +{
[snip]
> +      if (TREE_CODE (t) != FUNCTION_DECL)
> +        return 0;
   ^^^^^^^^
Same here.

> +      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;

Same here.

> +/* Returns 1 if FUNC has been assigned the attribute 
                                                       ^
Extra trailing space.

> +   "function_vector"  */

Missing period.

> +sh2a_function_vector_p (tree func)
[snip]
> +  while (list)
> +    {
> +      if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
> +        return 1;
   ^^^^^^^^
Use a tab.

> +sh_cfun_resbank_handler_p (void)
> +{
> +  return ((lookup_attribute ("resbank",
> +                              DECL_ATTRIBUTES (current_function_decl)) 
                                                                         ^
Extra trailing space

> +           != NULL_TREE)
> +           && (lookup_attribute ("interrupt_handler",
> +                                  DECL_ATTRIBUTES (current_function_decl)) 
                                                                             ^
and here.

> +           != NULL_TREE)
> +	  && TARGET_SH2A);

Wrong indentations.  Also use tabs.

>  static const char *
> diff -upr gcc-4.3-20070921/gcc/config/sh/sh.md tars/gcc-4.3-20070921/gcc/config/sh/sh.md
> --- gcc-4.3-20070921/gcc/config/sh/sh.md	2007-09-12 09:16:53.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/config/sh/sh.md	2007-10-24 12:00:23.000000000 +0530
> @@ -7437,7 +7437,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%#\";
   ^^^^^^^^
Use tabs.

> +(define_insn "calli_tbr_rel"
> +  [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
> +         (match_operand 1 "" ""))
   ^^^^^^^
Use a tab.

> +   (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 = sh2a_get_function_vector_number (operands[0]);

Long line.

> +  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")))
   ^^^^^^^^^^^^^^^^
Use tabs.

> +       if (TARGET_SH2A && (dbr_sequence_length () == 0))
> +           return \"jsr/n\\t@%1\";
> +       else
> +           return \"jsr\\t@%1%#\";
   ^^^^^^^^
Use a tab.

> +(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 TBR_REG))

Remove this comment.

> +{
> +  unsigned HOST_WIDE_INT vect_num = sh2a_get_function_vector_number (operands[1]);

Long line.

> +  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")))
   ^^^^^^^^^^^^^^^^
Use tabs.

> +   (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"))
> @@ -7709,6 +7772,16 @@ 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)

Wrong indentations at the last 2 lines.

> +      if (sh2a_is_function_vector_call (XEXP (operands[0], 0)))
> +        {
> +          emit_call_insn (gen_calli_tbr_rel (XEXP (operands[0], 0), operands[1]));

Long line.

> @@ -7892,6 +7965,16 @@ label:
[snip]
> +          emit_call_insn (gen_call_valuei_tbr_rel (operands[0], XEXP (operands[1], 0), operands[2]));

Long line.  Use a tab.

> +          DONE;
   ^^^^^^^^
Use a tab.

> --- gcc-4.3-20070921/gcc/doc/extend.texi	2007-09-20 21:25:33.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/doc/extend.texi	2007-10-24 11:48:18.000000000 +0530
[snip]
> +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
                                ^ Extra ;?

> --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	1970-01-01 05:30:00.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	2007-10-24 11:55:53.000000000 +0530
> @@ -0,0 +1,17 @@
> +/* Testcase to check generation of a SH2A specific instruction for
> +   "JSR/N @Rm"  */

Missing period.

> +/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single
> +   -m2a-single-only" }  */

A single line would be safer.

> --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c	1970-01-01 05:30:00.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-resbank.c	2007-10-24 11:48:18.000000000 +0530
> @@ -0,0 +1,14 @@
> + /* 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();
> + }
> +

Extra space at the head of each lines.

> --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	1970-01-01 05:30:00.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	2007-10-24 12:03:50.000000000 +0530
> @@ -0,0 +1,13 @@
> +/* Testcase to check generation of a SH2A specific instruction for
> +   "RTS/N"  */

Missing period.

> --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	1970-01-01 05:30:00.000000000 +0530
> +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	2007-10-24 11:48:18.000000000 +0530
> @@ -0,0 +1,25 @@
> +/* Testcase to check generation of a SH2A specific,
> +   TBR relative jump instruction - "JSR @@(disp8,TBR)"  */

Missing period.

> 2007-10-18	Anil Paranjape <anil.paranjape@kpitcummins.com>
>           	Jayant Sonar <Jayant.sonar@kpitcummins.com>

should be

200z-xx-yy  Anil Paranjape  <anil.paranjape@kpitcummins.com>
	    Jayant Sonar  <Jayant.sonar@kpitcummins.com>

> 	(print_operand): "@" prints resbank if the instruction RESBANK 
> 	has to be generated.

 	(print_operand): Handle resbank in %@ operand code.

would be better.

> 	(push_regs): Add conditions for resbank.
> 	(sh_expand_epilogue): Add conditions for resbank.
> 	(sh_insert_attributes): Add resbank attribute.
> 	(sh_attribute_table): Add resbank and function_vector
> 	attributes.

In such case,

 	(push_regs): Add conditions for resbank.
 	(sh_expand_epilogue): Likewise.
 	(sh_insert_attributes): Likewise.
 	(sh_attribute_table): Likewise.

is enough.

> 	* config/sh/sh.md: (calli): Add JSR/N instruction if the
> 	instruction does not have delay slot.

Wrong format.

	* config/sh/sh.md (calli): Emit jsr/n if possible.

is enough.

> 	(calli_pcrel): Add JSR/N instruction if the instruction does 
> 	not have delay slot.
> 	(return_i): Add RTS/N instruction if the instruction does not
> 	have delay slot.

	(calli_pcrel): Emit jsr/n if possible.
	(return_i): Emit rts/n if possible.

is enough.

> 	* config/sh/sh-protos.h : Update as needed.

Extra space before colon.  A little vague description.
	
	* config/sh/sh-protos.h (sh_cfun_resbank_handler_p): Declare.
	(sh2a_get_function_vector_number): Likewise.
	(sh2a_is_function_vector_call): Likewise.

would be better.

> 	* doc/extend.texi (TBR relative addressing): Added description 
> 	for SH2A target.
> 	(resbank): Added description for SH2A target.

should be

	* doc/extend.texi: Document TBR relative addressing of SH2A.
	(resbank): Add description for SH2A.

though the document changes will be looked by appropriate
maintainers.

> 	* testsuite/gcc.target/sh/sh2a-resbank.c : New.
> 	* testsuite/gcc.target/sh/sh2a-tbr-jump.c: New.

New testcases require an entry in gcc/testsuite/ChangeLog:

	* gcc.target/sh/sh2a-resbank.c: New test.
	* gcc.target/sh/sh2a-tbr-jump.c: New test.
	
Regards,
	kaz

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,SH] Add SH2A new instructions 1/6
  2008-03-25 12:30       ` Naveen H.S.
@ 2008-03-25 15:13         ` Kaz Kojima
  0 siblings, 0 replies; 8+ messages in thread
From: Kaz Kojima @ 2008-03-25 15:13 UTC (permalink / raw)
  To: naveen.hs; +Cc: gcc-patches, Prafulla.Thakare

"Naveen H.S." <naveen.hs@kpitcummins.com> wrote:
> We have tested the extend.texi file using the option "makeinfo --html 
> extend.texi". The generated HTML file included the changes in the patch
> as expected.

I've double-checked that with make dvi and make pdf.  Your patches
have been committed as revision 133513, 133514 and 13351[6-8] on trunk.
Thanks for your patches.

Regards,
	kaz

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH,SH] Add SH2A new instructions 1/6
  2008-03-24 14:02     ` Kaz Kojima
@ 2008-03-25 12:30       ` Naveen H.S.
  2008-03-25 15:13         ` Kaz Kojima
  0 siblings, 1 reply; 8+ messages in thread
From: Naveen H.S. @ 2008-03-25 12:30 UTC (permalink / raw)
  To: Kaz Kojima; +Cc: gcc-patches, Prafulla Thakare

[-- Attachment #1: Type: text/plain, Size: 997 bytes --]

Hi Kaz,

>> Did you test that change of extend.texi with make dvi/info/pdf?

We have tested the extend.texi file using the option "makeinfo --html 
extend.texi". The generated HTML file included the changes in the patch
as expected. Please find attached the final patch "sh2a1.patch".

>> If so, I'll check in your patch in 24 hours unless someone has
>> objections against the documentation change.

Thanks a lot for the valuable guidance and suggestions provided for 
all the patches.

Regards,
Naveen.H.S.
KPIT Cummins Infosystems Ltd,
Pune (INDIA) 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
Free download of GNU based tool-chains for Renesas' SH, H8, R8C, M16C	
and M32C Series. The following site also offers free technical support	
to its users. Visit http://www.kpitgnutools.com for details. 	
Latest versions of KPIT GNU tools were released on February 4, 2008.	
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

[-- Attachment #2: sh2a1.patch --]
[-- Type: application/octet-stream, Size: 24095 bytes --]

--- /gcc/config/sh/sh.c	2008-02-21 05:07:58.000000000 +0530
+++ /gcc/config/sh/sh.c	2008-03-24 12:43:21.000000000 +0530
@@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = COD
 #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 
 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 *);
@@ -257,6 +269,8 @@ static bool sh_callee_copies (CUMULATIVE
 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 			         tree, bool);
 static int sh_dwarf_calling_convention (const_tree);
+static void sh_encode_section_info (tree, rtx, int);
+static int sh2a_function_vector_p (tree);
 
 \f
 /* Initialize the GCC target structure.  */
@@ -446,6 +460,9 @@ static int sh_dwarf_calling_convention (
 /* 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
@@ -460,6 +477,9 @@ static int sh_dwarf_calling_convention (
 #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;
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -687,7 +707,11 @@ print_operand (FILE *stream, rtx x, int 
 	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;
@@ -1019,6 +1043,19 @@ print_operand (FILE *stream, rtx x, int 
     }
 }
 \f
+
+/* 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)
@@ -5764,7 +5801,16 @@ push_regs (HARD_REG_SET *mask, int inter
       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.  */
@@ -5773,7 +5819,8 @@ push_regs (HARD_REG_SET *mask, int inter
       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);
 }
 
@@ -6702,7 +6749,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 ());
@@ -6730,7 +6780,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)
@@ -7901,11 +7959,13 @@ sh_insert_attributes (tree node, tree *a
 	   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;
 
@@ -7913,7 +7973,8 @@ sh_insert_attributes (tree node, tree *a
 	    {
 	      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)));
@@ -7960,6 +8021,8 @@ sh_insert_attributes (tree node, tree *a
    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[] =
@@ -7971,6 +8034,8 @@ const struct attribute_spec sh_attribute
   { "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
@@ -7985,18 +8050,41 @@ const struct attribute_spec sh_attribute
   { 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)
@@ -8008,6 +8096,96 @@ sh_handle_interrupt_handler_attribute (t
   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
@@ -8098,6 +8276,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 *
--- /gcc/config/sh/sh.md	2008-02-21 05:05:41.000000000 +0530
+++ /gcc/config/sh/sh.md	2008-03-24 12:43:22.000000000 +0530
@@ -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")])
 
--- /gcc/config/sh/sh-protos.h	2007-12-06 18:55:37.000000000 +0530
+++ /gcc/config/sh/sh-protos.h	2008-03-24 12:43:22.000000000 +0530
@@ -134,6 +134,7 @@ extern int initial_elimination_offset (i
 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 */
 
--- /gcc/doc/extend.texi	2008-02-18 00:22:04.000000000 +0530
+++ /gcc/doc/extend.texi	2008-03-24 12:47:46.000000000 +0530
@@ -2290,16 +2290,33 @@ is used.  @xref{C Dialect Options,,Optio
 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
@@ -2713,6 +2730,19 @@ number of registers available if used in
 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
--- /gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,16 @@
+/* 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();
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-resbank.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-resbank.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,14 @@
+/* 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();
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,12 @@
+/* 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)
+{
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	2008-03-24 12:44:24.000000000 +0530
@@ -0,0 +1,23 @@
+/* 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();
+}
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,SH] Add SH2A new instructions 1/6
  2008-03-24 13:03   ` Naveen H.S.
@ 2008-03-24 14:02     ` Kaz Kojima
  2008-03-25 12:30       ` Naveen H.S.
  0 siblings, 1 reply; 8+ messages in thread
From: Kaz Kojima @ 2008-03-24 14:02 UTC (permalink / raw)
  To: naveen.hs; +Cc: gcc-patches, Prafulla.Thakare

"Naveen H.S." <naveen.hs@kpitcummins.com> wrote:
>>> The last line should be removed and there is no diff against 
>>> extend.texi in your sh2a1.patch.
> 
> The hunk was missed out in the posted patch. It has been added in 
> the present patch

Thanks!
Did you test that change of extend.texi with make dvi/info/pdf?
If so, I'll check in your patch in 24 hours unless someone has
objections against the documentation change.  I've attached that
part with plain text instead of an attachment. 

Regards,
	kaz
--
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/doc/extend.texi	2008-02-18 00:22:04.000000000 +0530
+++ gcc/doc/extend.texi	2008-03-24 12:47:46.000000000 +0530
@@ -2290,16 +2290,33 @@ is used.  @xref{C Dialect Options,,Optio
 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
@@ -2713,6 +2730,19 @@ number of registers available if used in
 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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH,SH] Add SH2A new instructions 1/6
  2008-03-20  1:40 ` Kaz Kojima
@ 2008-03-24 13:03   ` Naveen H.S.
  2008-03-24 14:02     ` Kaz Kojima
  0 siblings, 1 reply; 8+ messages in thread
From: Naveen H.S. @ 2008-03-24 13:03 UTC (permalink / raw)
  To: Kaz Kojima; +Cc: gcc-patches, Prafulla Thakare

[-- Attachment #1: Type: text/plain, Size: 2426 bytes --]

Hi Kaz,

>> The last line should be removed and there is no diff against 
>> extend.texi in your sh2a1.patch.

The hunk was missed out in the posted patch. It has been added in 
the present patch

>> It seems that the line of that test is unneeded in the first place.  
The line is removed from the testcase.

Please find the revised patch attached "sh2a1.patch" as per the
suggestions.

ChangeLog
2008-03-24  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): Add condition for SH2A target.
	* 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.
	(resbank): Added description for SH2A target.
	
	* 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.

Regards,
Naveen.H.S.
KPIT Cummins Infosystems Ltd,
Pune (INDIA) 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
Free download of GNU based tool-chains for Renesas' SH, H8, R8C, M16C	
and M32C Series. The following site also offers free technical support	
to its users. Visit http://www.kpitgnutools.com for details. 	
Latest versions of KPIT GNU tools were released on February 4, 2008.	
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

[-- Attachment #2: sh2a1.patch --]
[-- Type: application/octet-stream, Size: 25157 bytes --]

diff -upr /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh.c gcc/config/sh/sh.c
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh.c	2008-02-21 05:07:58.000000000 +0530
+++ gcc/config/sh/sh.c	2008-03-24 12:43:21.000000000 +0530
@@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = COD
 #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 
 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 *);
@@ -257,6 +269,8 @@ static bool sh_callee_copies (CUMULATIVE
 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 			         tree, bool);
 static int sh_dwarf_calling_convention (const_tree);
+static void sh_encode_section_info (tree, rtx, int);
+static int sh2a_function_vector_p (tree);
 
 \f
 /* Initialize the GCC target structure.  */
@@ -446,6 +460,9 @@ static int sh_dwarf_calling_convention (
 /* 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
@@ -460,6 +477,9 @@ static int sh_dwarf_calling_convention (
 #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;
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -687,7 +707,11 @@ print_operand (FILE *stream, rtx x, int 
 	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;
@@ -1019,6 +1043,19 @@ print_operand (FILE *stream, rtx x, int 
     }
 }
 \f
+
+/* 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)
@@ -5764,7 +5801,16 @@ push_regs (HARD_REG_SET *mask, int inter
       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.  */
@@ -5773,7 +5819,8 @@ push_regs (HARD_REG_SET *mask, int inter
       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);
 }
 
@@ -6702,7 +6749,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 ());
@@ -6730,7 +6780,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)
@@ -7901,11 +7959,13 @@ sh_insert_attributes (tree node, tree *a
 	   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;
 
@@ -7913,7 +7973,8 @@ sh_insert_attributes (tree node, tree *a
 	    {
 	      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)));
@@ -7960,6 +8021,8 @@ sh_insert_attributes (tree node, tree *a
    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[] =
@@ -7971,6 +8034,8 @@ const struct attribute_spec sh_attribute
   { "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
@@ -7985,18 +8050,41 @@ const struct attribute_spec sh_attribute
   { 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)
@@ -8008,6 +8096,96 @@ sh_handle_interrupt_handler_attribute (t
   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
@@ -8098,6 +8276,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 -upr /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh.md gcc/config/sh/sh.md
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh.md	2008-02-21 05:05:41.000000000 +0530
+++ gcc/config/sh/sh.md	2008-03-24 12:43:22.000000000 +0530
@@ -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 -upr /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh-protos.h gcc/config/sh/sh-protos.h
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/config/sh/sh-protos.h	2007-12-06 18:55:37.000000000 +0530
+++ gcc/config/sh/sh-protos.h	2008-03-24 12:43:22.000000000 +0530
@@ -134,6 +134,7 @@ extern int initial_elimination_offset (i
 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 */
 
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/doc/extend.texi	2008-02-18 00:22:04.000000000 +0530
+++ gcc/doc/extend.texi	2008-03-24 12:47:46.000000000 +0530
@@ -2290,16 +2290,33 @@ is used.  @xref{C Dialect Options,,Optio
 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
@@ -2713,6 +2730,19 @@ number of registers available if used in
 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 -uprN /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c gcc/testsuite/gcc.target/sh/sh2a-jsrn.c
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,16 @@
+/* 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 -uprN /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-resbank.c gcc/testsuite/gcc.target/sh/sh2a-resbank.c
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-resbank.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/sh/sh2a-resbank.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,14 @@
+/* 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 -uprN /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c gcc/testsuite/gcc.target/sh/sh2a-rtsn.c
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	2008-03-24 12:43:22.000000000 +0530
@@ -0,0 +1,12 @@
+/* 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 -uprN /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c
--- /home/naveenh/tars/gcc-4.4-20080222/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	2008-03-24 12:44:24.000000000 +0530
@@ -0,0 +1,23 @@
+/* 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();
+}
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH,SH] Add SH2A new instructions 1/6
  2008-03-19  6:48 Naveen H.S.
@ 2008-03-20  1:40 ` Kaz Kojima
  2008-03-24 13:03   ` Naveen H.S.
  0 siblings, 1 reply; 8+ messages in thread
From: Kaz Kojima @ 2008-03-20  1:40 UTC (permalink / raw)
  To: naveen.hs; +Cc: gcc-patches, Prafulla.Thakare

"Naveen H.S." <naveen.hs@kpitcummins.com> wrote:
>	  * doc/extend.texi: Document TBR relative addressing of SH2A.
>	  (resbank): Add description for SH2A.
>	  (resbank): Added description for SH2A target.

The last line should be removed and there is no diff against
extend.texi in your sh2a1.patch.
Please refer about the result of make dvi, make info and
make pdf if your patch touches a doc file.

Also, I've found a failure

FAIL: gcc.target/sh/sh2a-tbr-jump.c scan-assembler-times jsr\\t@r[0-9] 2

for the new sh2a-tbr-jump.c test with -m2a.  It seems that
the line

/* { dg-final { scan-assembler-times "jsr\\t@r\[0-9\]" 2} } */

of that test is unneeded in the first place.  

Regards,
	kaz

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH,SH] Add SH2A new instructions 1/6
@ 2008-03-19  6:48 Naveen H.S.
  2008-03-20  1:40 ` Kaz Kojima
  0 siblings, 1 reply; 8+ messages in thread
From: Naveen H.S. @ 2008-03-19  6:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: Kaz Kojima, Prafulla Thakare

[-- Attachment #1: Type: text/plain, Size: 2481 bytes --]

Hi Kaz,

>> find and fix them yourself and re-post the revised patch when the
>> trunk returns to stage1.

Please find the revised patch attached "sh2a1.patch" as per the
suggestions. Thanks a lot for the valuable guidance.

>> describe how the patch was tested more explicitly next time

The patch was tested using the C and C++ testsuite for all the SH2A
combinations.

ChangeLog
2008-03-19  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): Add condition for SH2A target.
	  * 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.
	  (resbank): Added description for SH2A target.
	
	  * 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.

Regards,
Naveen.H.S.
KPIT Cummins Infosystems Ltd,
Pune (INDIA) 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
Free download of GNU based tool-chains for Renesas' SH, H8, R8C, M16C	
and M32C Series. The following site also offers free technical support	
to its users. Visit http://www.kpitgnutools.com for details. 	
Latest versions of KPIT GNU tools were released on February 4, 2008.	
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

[-- Attachment #2: sh2a1.patch --]
[-- Type: application/octet-stream, Size: 21102 bytes --]

--- /gcc/config/sh/sh.c	2008-02-21 05:07:58.000000000 +0530
+++ /gcc/config/sh/sh.c	2008-03-19 10:05:56.000000000 +0530
@@ -69,6 +69,14 @@ int code_for_indirect_jump_scratch = COD
 #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 
 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 *);
@@ -257,6 +269,8 @@ static bool sh_callee_copies (CUMULATIVE
 static int sh_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 			         tree, bool);
 static int sh_dwarf_calling_convention (const_tree);
+static void sh_encode_section_info (tree, rtx, int);
+static int sh2a_function_vector_p (tree);
 
 \f
 /* Initialize the GCC target structure.  */
@@ -446,6 +460,9 @@ static int sh_dwarf_calling_convention (
 /* 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
@@ -460,6 +477,9 @@ static int sh_dwarf_calling_convention (
 #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;
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -687,7 +707,11 @@ print_operand (FILE *stream, rtx x, int 
 	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;
@@ -1019,6 +1043,19 @@ print_operand (FILE *stream, rtx x, int 
     }
 }
 \f
+
+/* 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)
@@ -5764,7 +5801,16 @@ push_regs (HARD_REG_SET *mask, int inter
       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.  */
@@ -5773,7 +5819,8 @@ push_regs (HARD_REG_SET *mask, int inter
       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);
 }
 
@@ -6702,7 +6749,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 ());
@@ -6730,7 +6780,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)
@@ -7901,11 +7959,13 @@ sh_insert_attributes (tree node, tree *a
 	   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;
 
@@ -7913,7 +7973,8 @@ sh_insert_attributes (tree node, tree *a
 	    {
 	      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)));
@@ -7960,6 +8021,8 @@ sh_insert_attributes (tree node, tree *a
    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[] =
@@ -7971,6 +8034,8 @@ const struct attribute_spec sh_attribute
   { "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
@@ -7985,18 +8050,41 @@ const struct attribute_spec sh_attribute
   { 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)
@@ -8008,6 +8096,96 @@ sh_handle_interrupt_handler_attribute (t
   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
@@ -8098,6 +8276,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 *
--- /gcc/config/sh/sh.md	2008-02-21 05:05:41.000000000 +0530
+++ /gcc/config/sh/sh.md	2008-03-19 10:04:07.000000000 +0530
@@ -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")])
 
--- /gcc/config/sh/sh-protos.h	2007-12-06 18:55:37.000000000 +0530
+++ /gcc/config/sh/sh-protos.h	2008-03-19 10:04:07.000000000 +0530
@@ -134,6 +134,7 @@ extern int initial_elimination_offset (i
 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 */
 
--- /gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-jsrn.c	2008-03-19 10:04:07.000000000 +0530
@@ -0,0 +1,16 @@
+/* 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();
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-resbank.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-resbank.c	2008-03-19 10:04:07.000000000 +0530
@@ -0,0 +1,14 @@
+/* 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();
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-rtsn.c	2008-03-19 10:04:07.000000000 +0530
@@ -0,0 +1,12 @@
+/* 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)
+{
+}
+
--- /gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	1970-01-01 05:30:00.000000000 +0530
+++ /gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c	2008-03-19 10:04:07.000000000 +0530
@@ -0,0 +1,24 @@
+/* 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\\t@r\[0-9\]" 2} } */
+/* { 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();
+}
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-03-25 13:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-25 12:15 [PATCH,SH] Add SH2A new instructions 1/6 Naveen H.S.
2007-10-29  1:34 ` Kaz Kojima
2008-03-19  6:48 Naveen H.S.
2008-03-20  1:40 ` Kaz Kojima
2008-03-24 13:03   ` Naveen H.S.
2008-03-24 14:02     ` Kaz Kojima
2008-03-25 12:30       ` Naveen H.S.
2008-03-25 15:13         ` Kaz Kojima

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).