]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Move ISR impelentation to nds32-isr.c module.
authorChung-Ju Wu <jasonwucj@gmail.com>
Fri, 4 Jul 2014 07:23:32 +0000 (07:23 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Fri, 4 Jul 2014 07:23:32 +0000 (07:23 +0000)
gcc/
* config/nds32/nds32.c (nds32_emit_section_head_template): Move to ...
(nds32_emit_section_tail_template): Move to ...
(nds32_emit_isr_jmptbl_section): Move to ...
(nds32_emit_isr_vector_section): Move to ...
(nds32_emit_isr_reset_conten): Move to ...
(nds32_check_isr_attrs_conflict): Move to ...
(nds32_construct_isr_vectors_information): Move to ...
(nds32_asm_file_start): Move implementation to ...
(nds32_asm_file_end): Move implementation to ...
* config/nds32/nds32-isr.c: ... here.
* config/nds32/nds32-protos.h
(nds32_check_isr_attrs_conflict): Declare.
(nds32_construct_isr_vectors_information): Declare.
(nds32_asm_file_start_for_isr): Declare.
(nds32_asm_file_end_for_isr): Declare.

Co-Authored-By: Kito Cheng <kito@0xlab.org>
Co-Authored-By: Monk Chiang <sh.chiang04@gmail.com>
From-SVN: r212281

gcc/ChangeLog
gcc/config/nds32/nds32-isr.c
gcc/config/nds32/nds32-protos.h
gcc/config/nds32/nds32.c

index 0f7bfd232fccea31ba204da376623fe21b39be51..7979ab7aa0ca268d0787e6f9e062534d131280b2 100644 (file)
@@ -1,3 +1,23 @@
+2014-07-04  Chung-Ju Wu  <jasonwucj@gmail.com>
+           Kito Cheng  <kito@0xlab.org>
+           Monk Chiang  <sh.chiang04@gmail.com>
+
+       * config/nds32/nds32.c (nds32_emit_section_head_template): Move to ...
+       (nds32_emit_section_tail_template): Move to ...
+       (nds32_emit_isr_jmptbl_section): Move to ...
+       (nds32_emit_isr_vector_section): Move to ...
+       (nds32_emit_isr_reset_conten): Move to ...
+       (nds32_check_isr_attrs_conflict): Move to ...
+       (nds32_construct_isr_vectors_information): Move to ...
+       (nds32_asm_file_start): Move implementation to ...
+       (nds32_asm_file_end): Move implementation to ...
+       * config/nds32/nds32-isr.c: ... here.
+       * config/nds32/nds32-protos.h
+       (nds32_check_isr_attrs_conflict): Declare.
+       (nds32_construct_isr_vectors_information): Declare.
+       (nds32_asm_file_start_for_isr): Declare.
+       (nds32_asm_file_end_for_isr): Declare.
+
 2014-07-04  Chung-Ju Wu  <jasonwucj@gmail.com>
            Kito Cheng  <kito@0xlab.org>
            Monk Chiang  <sh.chiang04@gmail.com>
index bf0f84ae196e95ad92f9a2d8360143c1be078936..ef0187c39cf9eabb3d9aeea4a24a8c5cdb53bc9b 100644 (file)
    You should have received a copy of the GNU General Public License
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
+
+/* ------------------------------------------------------------------------ */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "calls.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"       /* Required by recog.h.  */
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h"         /* For DFA state_t.  */
+#include "insn-codes.h"                /* For CODE_FOR_xxx.  */
+#include "reload.h"            /* For push_reload().  */
+#include "flags.h"
+#include "function.h"
+#include "expr.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "df.h"
+#include "tm_p.h"
+#include "tm-constrs.h"
+#include "optabs.h"            /* For GEN_FCN.  */
+#include "target.h"
+#include "target-def.h"
+#include "langhooks.h"         /* For add_builtin_function().  */
+#include "ggc.h"
+#include "builtins.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
+   0 for reset handler with __attribute__((reset())),
+   1-8 for exception handler with __attribute__((exception(1,...,8))),
+   and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
+   We use an array to record essential information for each vector.  */
+static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
+
+/* ------------------------------------------------------------------------ */
+
+/* A helper function to emit section head template.  */
+static void
+nds32_emit_section_head_template (char section_name[],
+                                 char symbol_name[],
+                                 int align_value,
+                                 bool object_p)
+{
+  const char *flags_str;
+  const char *type_str;
+
+  flags_str = (object_p) ? "\"a\"" : "\"ax\"";
+  type_str = (object_p) ? "@object" : "@function";
+
+  fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str);
+  fprintf (asm_out_file, "\t.align\t%d\n", align_value);
+  fprintf (asm_out_file, "\t.global\t%s\n", symbol_name);
+  fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str);
+  fprintf (asm_out_file, "%s:\n", symbol_name);
+}
+
+/* A helper function to emit section tail template.  */
+static void
+nds32_emit_section_tail_template (char symbol_name[])
+{
+  fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name);
+}
+
+/* Function to emit isr jump table section.  */
+static void
+nds32_emit_isr_jmptbl_section (int vector_id)
+{
+  char section_name[100];
+  char symbol_name[100];
+
+  /* Prepare jmptbl section and symbol name.  */
+  snprintf (section_name, sizeof (section_name),
+           ".nds32_jmptbl.%02d", vector_id);
+  snprintf (symbol_name, sizeof (symbol_name),
+           "_nds32_jmptbl_%02d", vector_id);
+
+  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+  fprintf (asm_out_file, "\t.word\t%s\n",
+                        nds32_isr_vectors[vector_id].func_name);
+  nds32_emit_section_tail_template (symbol_name);
+}
+
+/* Function to emit isr vector section.  */
+static void
+nds32_emit_isr_vector_section (int vector_id)
+{
+  unsigned int vector_number_offset = 0;
+  const char *c_str = "CATEGORY";
+  const char *sr_str = "SR";
+  const char *nt_str = "NT";
+  const char *vs_str = "VS";
+  char first_level_handler_name[100];
+  char section_name[100];
+  char symbol_name[100];
+
+  /* Set the vector number offset so that we can calculate
+     the value that user specifies in the attribute.
+     We also prepare the category string for first level handler name.  */
+  switch (nds32_isr_vectors[vector_id].category)
+    {
+    case NDS32_ISR_INTERRUPT:
+      vector_number_offset = 9;
+      c_str = "i";
+      break;
+    case NDS32_ISR_EXCEPTION:
+      vector_number_offset = 0;
+      c_str = "e";
+      break;
+    case NDS32_ISR_NONE:
+    case NDS32_ISR_RESET:
+      /* Normally it should not be here.  */
+      gcc_unreachable ();
+      break;
+    }
+
+  /* Prepare save reg string for first level handler name.  */
+  switch (nds32_isr_vectors[vector_id].save_reg)
+    {
+    case NDS32_SAVE_ALL:
+      sr_str = "sa";
+      break;
+    case NDS32_PARTIAL_SAVE:
+      sr_str = "ps";
+      break;
+    }
+
+  /* Prepare nested type string for first level handler name.  */
+  switch (nds32_isr_vectors[vector_id].nested_type)
+    {
+    case NDS32_NESTED:
+      nt_str = "ns";
+      break;
+    case NDS32_NOT_NESTED:
+      nt_str = "nn";
+      break;
+    case NDS32_NESTED_READY:
+      nt_str = "nr";
+      break;
+    }
+
+  /* Currently we have 4-byte or 16-byte size for each vector.
+     If it is 4-byte, the first level handler name has suffix string "_4b".  */
+  vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
+
+  /* Now we can create first level handler name.  */
+  snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+           "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
+
+  /* Prepare vector section and symbol name.  */
+  snprintf (section_name, sizeof (section_name),
+           ".nds32_vector.%02d", vector_id);
+  snprintf (symbol_name, sizeof (symbol_name),
+           "_nds32_vector_%02d%s", vector_id, vs_str);
+
+
+  /* Everything is ready.  We can start emit vector section content.  */
+  nds32_emit_section_head_template (section_name, symbol_name,
+                                   floor_log2 (nds32_isr_vector_size), false);
+
+  /* According to the vector size, the instructions in the
+     vector section may be different.  */
+  if (nds32_isr_vector_size == 4)
+    {
+      /* This block is for 4-byte vector size.
+         Hardware $VID support is necessary and only one instruction
+         is needed in vector section.  */
+      fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
+                            first_level_handler_name);
+    }
+  else
+    {
+      /* This block is for 16-byte vector size.
+         There is NO hardware $VID so that we need several instructions
+         such as pushing GPRs and preparing software vid at vector section.
+         For pushing GPRs, there are four variations for
+         16-byte vector content and we have to handle each combination.
+         For preparing software vid, note that the vid need to
+         be substracted vector_number_offset.  */
+      if (TARGET_REDUCED_REGS)
+       {
+         if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
+           {
+             /* Case of reduced set registers and save_all attribute.  */
+             fprintf (asm_out_file, "\t! reduced set regs + save_all\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
+
+           }
+         else
+           {
+             /* Case of reduced set registers and partial_save attribute.  */
+             fprintf (asm_out_file, "\t! reduced set regs + partial_save\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
+           }
+       }
+      else
+       {
+         if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
+           {
+             /* Case of full set registers and save_all attribute.  */
+             fprintf (asm_out_file, "\t! full set regs + save_all\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
+           }
+         else
+           {
+             /* Case of full set registers and partial_save attribute.  */
+             fprintf (asm_out_file, "\t! full set regs + partial_save\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
+             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
+           }
+       }
+
+      fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n",
+                            vector_id - vector_number_offset);
+      fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
+                            first_level_handler_name);
+    }
+
+  nds32_emit_section_tail_template (symbol_name);
+}
+
+/* Function to emit isr reset handler content.
+   Including all jmptbl/vector references, jmptbl section,
+   vector section, nmi handler section, and warm handler section.  */
+static void
+nds32_emit_isr_reset_content (void)
+{
+  unsigned int i;
+  unsigned int total_n_vectors;
+  const char *vs_str;
+  char reset_handler_name[100];
+  char section_name[100];
+  char symbol_name[100];
+
+  total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
+  vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
+
+  fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
+
+  /* Create references in .rodata according to total number of vectors.  */
+  fprintf (asm_out_file, "\t.section\t.rodata\n");
+  fprintf (asm_out_file, "\t.align\t2\n");
+
+  /* Emit jmptbl references.  */
+  fprintf (asm_out_file, "\t ! references to jmptbl section entries\n");
+  for (i = 0; i < total_n_vectors; i++)
+    fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i);
+
+  /* Emit vector references.  */
+  fprintf (asm_out_file, "\t ! references to vector section entries\n");
+  for (i = 0; i < total_n_vectors; i++)
+    fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
+
+  /* Emit jmptbl_00 section.  */
+  snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
+  snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00");
+
+  fprintf (asm_out_file, "\t! ....................................\n");
+  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+  fprintf (asm_out_file, "\t.word\t%s\n",
+                        nds32_isr_vectors[0].func_name);
+  nds32_emit_section_tail_template (symbol_name);
+
+  /* Emit vector_00 section.  */
+  snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
+  snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
+  snprintf (reset_handler_name, sizeof (reset_handler_name),
+           "_nds32_reset%s", vs_str);
+
+  fprintf (asm_out_file, "\t! ....................................\n");
+  nds32_emit_section_head_template (section_name, symbol_name,
+                                   floor_log2 (nds32_isr_vector_size), false);
+  fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n",
+                        reset_handler_name);
+  nds32_emit_section_tail_template (symbol_name);
+
+  /* Emit nmi handler section.  */
+  snprintf (section_name, sizeof (section_name), ".nds32_nmih");
+  snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih");
+
+  fprintf (asm_out_file, "\t! ....................................\n");
+  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+  fprintf (asm_out_file, "\t.word\t%s\n",
+                        (strlen (nds32_isr_vectors[0].nmi_name) == 0)
+                        ? "0"
+                        : nds32_isr_vectors[0].nmi_name);
+  nds32_emit_section_tail_template (symbol_name);
+
+  /* Emit warm handler section.  */
+  snprintf (section_name, sizeof (section_name), ".nds32_wrh");
+  snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh");
+
+  fprintf (asm_out_file, "\t! ....................................\n");
+  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+  fprintf (asm_out_file, "\t.word\t%s\n",
+                        (strlen (nds32_isr_vectors[0].warm_name) == 0)
+                        ? "0"
+                        : nds32_isr_vectors[0].warm_name);
+  nds32_emit_section_tail_template (symbol_name);
+
+  fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n");
+}
+
+/* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
+   to check if there are any conflict isr-specific attributes being set.
+   We need to check:
+     1. Only 'save_all' or 'partial_save' in the attributes.
+     2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
+     3. Only 'interrupt', 'exception', or 'reset' in the attributes.  */
+void
+nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
+{
+  int save_all_p, partial_save_p;
+  int nested_p, not_nested_p, nested_ready_p;
+  int intr_p, excp_p, reset_p;
+
+  /* Initialize variables.  */
+  save_all_p = partial_save_p = 0;
+  nested_p = not_nested_p = nested_ready_p = 0;
+  intr_p = excp_p = reset_p = 0;
+
+  /* We must check at MOST one attribute to set save-reg.  */
+  if (lookup_attribute ("save_all", func_attrs))
+    save_all_p = 1;
+  if (lookup_attribute ("partial_save", func_attrs))
+    partial_save_p = 1;
+
+  if ((save_all_p + partial_save_p) > 1)
+    error ("multiple save reg attributes to function %qD", func_decl);
+
+  /* We must check at MOST one attribute to set nested-type.  */
+  if (lookup_attribute ("nested", func_attrs))
+    nested_p = 1;
+  if (lookup_attribute ("not_nested", func_attrs))
+    not_nested_p = 1;
+  if (lookup_attribute ("nested_ready", func_attrs))
+    nested_ready_p = 1;
+
+  if ((nested_p + not_nested_p + nested_ready_p) > 1)
+    error ("multiple nested types attributes to function %qD", func_decl);
+
+  /* We must check at MOST one attribute to
+     set interrupt/exception/reset.  */
+  if (lookup_attribute ("interrupt", func_attrs))
+    intr_p = 1;
+  if (lookup_attribute ("exception", func_attrs))
+    excp_p = 1;
+  if (lookup_attribute ("reset", func_attrs))
+    reset_p = 1;
+
+  if ((intr_p + excp_p + reset_p) > 1)
+    error ("multiple interrupt attributes to function %qD", func_decl);
+}
+
+/* Function to construct isr vectors information array.
+   We DO NOT HAVE TO check if the attributes are valid
+   because those works are supposed to be done on
+   nds32_merge_decl_attributes() and nds32_insert_attributes().  */
+void
+nds32_construct_isr_vectors_information (tree func_attrs,
+                                        const char *func_name)
+{
+  tree save_all, partial_save;
+  tree nested, not_nested, nested_ready;
+  tree intr, excp, reset;
+
+  save_all     = lookup_attribute ("save_all", func_attrs);
+  partial_save = lookup_attribute ("partial_save", func_attrs);
+
+  nested       = lookup_attribute ("nested", func_attrs);
+  not_nested   = lookup_attribute ("not_nested", func_attrs);
+  nested_ready = lookup_attribute ("nested_ready", func_attrs);
+
+  intr  = lookup_attribute ("interrupt", func_attrs);
+  excp  = lookup_attribute ("exception", func_attrs);
+  reset = lookup_attribute ("reset", func_attrs);
+
+  /* If there is no interrupt/exception/reset, we can return immediately.  */
+  if (!intr && !excp && !reset)
+    return;
+
+  /* If we are here, either we have interrupt/exception,
+     or reset attribute.  */
+  if (intr || excp)
+    {
+      tree id_list;
+
+      /* Prepare id list so that we can traverse and set vector id.  */
+      id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
+
+      while (id_list)
+       {
+         tree id;
+         int vector_id;
+         unsigned int vector_number_offset;
+
+         /* The way to handle interrupt or exception is the same,
+            we just need to take care of actual vector number.
+            For interrupt(0..63), the actual vector number is (9..72).
+            For exception(1..8), the actual vector number is (1..8).  */
+         vector_number_offset = (intr) ? (9) : (0);
+
+         /* Pick up each vector id value.  */
+         id = TREE_VALUE (id_list);
+         /* Add vector_number_offset to get actual vector number.  */
+         vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
+
+         /* Enable corresponding vector and set function name.  */
+         nds32_isr_vectors[vector_id].category = (intr)
+                                                 ? (NDS32_ISR_INTERRUPT)
+                                                 : (NDS32_ISR_EXCEPTION);
+         strcpy (nds32_isr_vectors[vector_id].func_name, func_name);
+
+         /* Set register saving scheme.  */
+         if (save_all)
+           nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL;
+         else if (partial_save)
+           nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE;
+
+         /* Set nested type.  */
+         if (nested)
+           nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED;
+         else if (not_nested)
+           nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
+         else if (nested_ready)
+           nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
+
+         /* Advance to next id.  */
+         id_list = TREE_CHAIN (id_list);
+       }
+    }
+  else
+    {
+      tree id_list;
+      tree id;
+      tree nmi, warm;
+
+      /* Deal with reset attribute.  Its vector number is always 0.  */
+      nds32_isr_vectors[0].category = NDS32_ISR_RESET;
+
+      /* Prepare id_list and identify id value so that
+         we can set total number of vectors.  */
+      id_list = TREE_VALUE (reset);
+      id = TREE_VALUE (id_list);
+
+      /* The total vectors = interrupt + exception numbers + reset.
+         There are 8 exception and 1 reset in nds32 architecture.  */
+      nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1;
+      strcpy (nds32_isr_vectors[0].func_name, func_name);
+
+      /* Retrieve nmi and warm function.  */
+      nmi  = lookup_attribute ("nmi", func_attrs);
+      warm = lookup_attribute ("warm", func_attrs);
+
+      if (nmi != NULL_TREE)
+       {
+         tree nmi_func_list;
+         tree nmi_func;
+
+         nmi_func_list = TREE_VALUE (nmi);
+         nmi_func = TREE_VALUE (nmi_func_list);
+
+         /* Record nmi function name.  */
+         strcpy (nds32_isr_vectors[0].nmi_name,
+                 IDENTIFIER_POINTER (nmi_func));
+       }
+
+      if (warm != NULL_TREE)
+       {
+         tree warm_func_list;
+         tree warm_func;
+
+         warm_func_list = TREE_VALUE (warm);
+         warm_func = TREE_VALUE (warm_func_list);
+
+         /* Record warm function name.  */
+         strcpy (nds32_isr_vectors[0].warm_name,
+                 IDENTIFIER_POINTER (warm_func));
+       }
+    }
+}
+
+/* A helper function to handle isr stuff at the beginning of asm file.  */
+void
+nds32_asm_file_start_for_isr (void)
+{
+  int i;
+
+  /* Initialize isr vector information array before compiling functions.  */
+  for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
+    {
+      nds32_isr_vectors[i].category = NDS32_ISR_NONE;
+      strcpy (nds32_isr_vectors[i].func_name, "");
+      nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
+      nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
+      nds32_isr_vectors[i].total_n_vectors = 0;
+      strcpy (nds32_isr_vectors[i].nmi_name, "");
+      strcpy (nds32_isr_vectors[i].warm_name, "");
+    }
+}
+
+/* A helper function to handle isr stuff at the end of asm file.  */
+void
+nds32_asm_file_end_for_isr (void)
+{
+  int i;
+
+  /* If all the vectors are NDS32_ISR_NONE, we can return immediately.  */
+  for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
+    if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
+      break;
+
+  if (i == NDS32_N_ISR_VECTORS)
+    return;
+
+  /* At least one vector is NOT NDS32_ISR_NONE,
+     we should output isr vector information.  */
+  fprintf (asm_out_file, "\t! ------------------------------------\n");
+  fprintf (asm_out_file, "\t! The isr vector information:\n");
+  fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+  /* Check reset handler first.  Its vector number is always 0.  */
+  if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
+    {
+      nds32_emit_isr_reset_content ();
+      fprintf (asm_out_file, "\t! ------------------------------------\n");
+    }
+
+  /* Check other vectors, starting from vector number 1.  */
+  for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
+    {
+      if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
+         || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
+       {
+         /* Found one vector which is interupt or exception.
+            Output its jmptbl and vector section content.  */
+         fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
+         fprintf (asm_out_file, "\t! ------------------------------------\n");
+         nds32_emit_isr_jmptbl_section (i);
+         fprintf (asm_out_file, "\t! ....................................\n");
+         nds32_emit_isr_vector_section (i);
+         fprintf (asm_out_file, "\t! ------------------------------------\n");
+       }
+    }
+}
+
+/* ------------------------------------------------------------------------ */
index 6d94027bb6e893435da7a5aaaeab5027e7782684..f5b15abe69ba066cfac146105fb8af76b8aa980c 100644 (file)
@@ -125,4 +125,11 @@ extern const char *nds32_output_stack_pop (void);
 
 extern int nds32_target_alignment (rtx);
 
+/* Auxiliary functions for ISR implementation.  */
+
+extern void nds32_check_isr_attrs_conflict (tree, tree);
+extern void nds32_construct_isr_vectors_information (tree, const char *);
+extern void nds32_asm_file_start_for_isr (void);
+extern void nds32_asm_file_end_for_isr (void);
+
 /* ------------------------------------------------------------------------ */
index 8516221b25d0340bf9dd94b9452b9cbb46ee72d2..746a5e193875ebd86196a4edcbbfb61a07bf3330 100644 (file)
 /* PART 1: Auxiliary static variable definitions and
            target hook static variable definitions.  */
 
-/* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
-   0 for reset handler with __attribute__((reset())),
-   1-8 for exception handler with __attribute__((exception(1,...,8))),
-   and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
-   We use an array to record essential information for each vector.  */
-static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
-
 /* Define intrinsic register names.
    Please refer to nds32_intrinsic.h file, the index is corresponding to
    'enum nds32_intrinsic_registers' data type values.
@@ -907,453 +900,6 @@ nds32_consecutive_registers_load_store_p (rtx op,
   return true;
 }
 
-/* A helper function to emit section head template.  */
-static void
-nds32_emit_section_head_template (char section_name[],
-                                 char symbol_name[],
-                                 int align_value,
-                                 bool object_p)
-{
-  const char *flags_str;
-  const char *type_str;
-
-  flags_str = (object_p) ? "\"a\"" : "\"ax\"";
-  type_str = (object_p) ? "@object" : "@function";
-
-  fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str);
-  fprintf (asm_out_file, "\t.align\t%d\n", align_value);
-  fprintf (asm_out_file, "\t.global\t%s\n", symbol_name);
-  fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str);
-  fprintf (asm_out_file, "%s:\n", symbol_name);
-}
-
-/* A helper function to emit section tail template.  */
-static void
-nds32_emit_section_tail_template (char symbol_name[])
-{
-  fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name);
-}
-
-/* Function to emit isr jump table section.  */
-static void
-nds32_emit_isr_jmptbl_section (int vector_id)
-{
-  char section_name[100];
-  char symbol_name[100];
-
-  /* Prepare jmptbl section and symbol name.  */
-  snprintf (section_name, sizeof (section_name),
-           ".nds32_jmptbl.%02d", vector_id);
-  snprintf (symbol_name, sizeof (symbol_name),
-           "_nds32_jmptbl_%02d", vector_id);
-
-  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
-  fprintf (asm_out_file, "\t.word\t%s\n",
-                        nds32_isr_vectors[vector_id].func_name);
-  nds32_emit_section_tail_template (symbol_name);
-}
-
-/* Function to emit isr vector section.  */
-static void
-nds32_emit_isr_vector_section (int vector_id)
-{
-  unsigned int vector_number_offset = 0;
-  const char *c_str = "CATEGORY";
-  const char *sr_str = "SR";
-  const char *nt_str = "NT";
-  const char *vs_str = "VS";
-  char first_level_handler_name[100];
-  char section_name[100];
-  char symbol_name[100];
-
-  /* Set the vector number offset so that we can calculate
-     the value that user specifies in the attribute.
-     We also prepare the category string for first level handler name.  */
-  switch (nds32_isr_vectors[vector_id].category)
-    {
-    case NDS32_ISR_INTERRUPT:
-      vector_number_offset = 9;
-      c_str = "i";
-      break;
-    case NDS32_ISR_EXCEPTION:
-      vector_number_offset = 0;
-      c_str = "e";
-      break;
-    case NDS32_ISR_NONE:
-    case NDS32_ISR_RESET:
-      /* Normally it should not be here.  */
-      gcc_unreachable ();
-      break;
-    }
-
-  /* Prepare save reg string for first level handler name.  */
-  switch (nds32_isr_vectors[vector_id].save_reg)
-    {
-    case NDS32_SAVE_ALL:
-      sr_str = "sa";
-      break;
-    case NDS32_PARTIAL_SAVE:
-      sr_str = "ps";
-      break;
-    }
-
-  /* Prepare nested type string for first level handler name.  */
-  switch (nds32_isr_vectors[vector_id].nested_type)
-    {
-    case NDS32_NESTED:
-      nt_str = "ns";
-      break;
-    case NDS32_NOT_NESTED:
-      nt_str = "nn";
-      break;
-    case NDS32_NESTED_READY:
-      nt_str = "nr";
-      break;
-    }
-
-  /* Currently we have 4-byte or 16-byte size for each vector.
-     If it is 4-byte, the first level handler name has suffix string "_4b".  */
-  vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
-
-  /* Now we can create first level handler name.  */
-  snprintf (first_level_handler_name, sizeof (first_level_handler_name),
-           "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
-
-  /* Prepare vector section and symbol name.  */
-  snprintf (section_name, sizeof (section_name),
-           ".nds32_vector.%02d", vector_id);
-  snprintf (symbol_name, sizeof (symbol_name),
-           "_nds32_vector_%02d%s", vector_id, vs_str);
-
-
-  /* Everything is ready.  We can start emit vector section content.  */
-  nds32_emit_section_head_template (section_name, symbol_name,
-                                   floor_log2 (nds32_isr_vector_size), false);
-
-  /* According to the vector size, the instructions in the
-     vector section may be different.  */
-  if (nds32_isr_vector_size == 4)
-    {
-      /* This block is for 4-byte vector size.
-         Hardware $VID support is necessary and only one instruction
-         is needed in vector section.  */
-      fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
-                            first_level_handler_name);
-    }
-  else
-    {
-      /* This block is for 16-byte vector size.
-         There is NO hardware $VID so that we need several instructions
-         such as pushing GPRs and preparing software vid at vector section.
-         For pushing GPRs, there are four variations for
-         16-byte vector content and we have to handle each combination.
-         For preparing software vid, note that the vid need to
-         be substracted vector_number_offset.  */
-      if (TARGET_REDUCED_REGS)
-       {
-         if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
-           {
-             /* Case of reduced set registers and save_all attribute.  */
-             fprintf (asm_out_file, "\t! reduced set regs + save_all\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
-
-           }
-         else
-           {
-             /* Case of reduced set registers and partial_save attribute.  */
-             fprintf (asm_out_file, "\t! reduced set regs + partial_save\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
-           }
-       }
-      else
-       {
-         if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
-           {
-             /* Case of full set registers and save_all attribute.  */
-             fprintf (asm_out_file, "\t! full set regs + save_all\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
-           }
-         else
-           {
-             /* Case of full set registers and partial_save attribute.  */
-             fprintf (asm_out_file, "\t! full set regs + partial_save\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
-             fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
-           }
-       }
-
-      fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n",
-                            vector_id - vector_number_offset);
-      fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
-                            first_level_handler_name);
-    }
-
-  nds32_emit_section_tail_template (symbol_name);
-}
-
-/* Function to emit isr reset handler content.
-   Including all jmptbl/vector references, jmptbl section,
-   vector section, nmi handler section, and warm handler section.  */
-static void
-nds32_emit_isr_reset_content (void)
-{
-  unsigned int i;
-  unsigned int total_n_vectors;
-  const char *vs_str;
-  char reset_handler_name[100];
-  char section_name[100];
-  char symbol_name[100];
-
-  total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
-  vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
-
-  fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
-
-  /* Create references in .rodata according to total number of vectors.  */
-  fprintf (asm_out_file, "\t.section\t.rodata\n");
-  fprintf (asm_out_file, "\t.align\t2\n");
-
-  /* Emit jmptbl references.  */
-  fprintf (asm_out_file, "\t ! references to jmptbl section entries\n");
-  for (i = 0; i < total_n_vectors; i++)
-    fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i);
-
-  /* Emit vector references.  */
-  fprintf (asm_out_file, "\t ! references to vector section entries\n");
-  for (i = 0; i < total_n_vectors; i++)
-    fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
-
-  /* Emit jmptbl_00 section.  */
-  snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
-  snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00");
-
-  fprintf (asm_out_file, "\t! ....................................\n");
-  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
-  fprintf (asm_out_file, "\t.word\t%s\n",
-                        nds32_isr_vectors[0].func_name);
-  nds32_emit_section_tail_template (symbol_name);
-
-  /* Emit vector_00 section.  */
-  snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
-  snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
-  snprintf (reset_handler_name, sizeof (reset_handler_name),
-           "_nds32_reset%s", vs_str);
-
-  fprintf (asm_out_file, "\t! ....................................\n");
-  nds32_emit_section_head_template (section_name, symbol_name,
-                                   floor_log2 (nds32_isr_vector_size), false);
-  fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n",
-                        reset_handler_name);
-  nds32_emit_section_tail_template (symbol_name);
-
-  /* Emit nmi handler section.  */
-  snprintf (section_name, sizeof (section_name), ".nds32_nmih");
-  snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih");
-
-  fprintf (asm_out_file, "\t! ....................................\n");
-  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
-  fprintf (asm_out_file, "\t.word\t%s\n",
-                        (strlen (nds32_isr_vectors[0].nmi_name) == 0)
-                        ? "0"
-                        : nds32_isr_vectors[0].nmi_name);
-  nds32_emit_section_tail_template (symbol_name);
-
-  /* Emit warm handler section.  */
-  snprintf (section_name, sizeof (section_name), ".nds32_wrh");
-  snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh");
-
-  fprintf (asm_out_file, "\t! ....................................\n");
-  nds32_emit_section_head_template (section_name, symbol_name, 2, true);
-  fprintf (asm_out_file, "\t.word\t%s\n",
-                        (strlen (nds32_isr_vectors[0].warm_name) == 0)
-                        ? "0"
-                        : nds32_isr_vectors[0].warm_name);
-  nds32_emit_section_tail_template (symbol_name);
-
-  fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n");
-}
-
-/* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
-   to check if there are any conflict isr-specific attributes being set.
-   We need to check:
-     1. Only 'save_all' or 'partial_save' in the attributes.
-     2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
-     3. Only 'interrupt', 'exception', or 'reset' in the attributes.  */
-static void
-nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
-{
-  int save_all_p, partial_save_p;
-  int nested_p, not_nested_p, nested_ready_p;
-  int intr_p, excp_p, reset_p;
-
-  /* Initialize variables.  */
-  save_all_p = partial_save_p = 0;
-  nested_p = not_nested_p = nested_ready_p = 0;
-  intr_p = excp_p = reset_p = 0;
-
-  /* We must check at MOST one attribute to set save-reg.  */
-  if (lookup_attribute ("save_all", func_attrs))
-    save_all_p = 1;
-  if (lookup_attribute ("partial_save", func_attrs))
-    partial_save_p = 1;
-
-  if ((save_all_p + partial_save_p) > 1)
-    error ("multiple save reg attributes to function %qD", func_decl);
-
-  /* We must check at MOST one attribute to set nested-type.  */
-  if (lookup_attribute ("nested", func_attrs))
-    nested_p = 1;
-  if (lookup_attribute ("not_nested", func_attrs))
-    not_nested_p = 1;
-  if (lookup_attribute ("nested_ready", func_attrs))
-    nested_ready_p = 1;
-
-  if ((nested_p + not_nested_p + nested_ready_p) > 1)
-    error ("multiple nested types attributes to function %qD", func_decl);
-
-  /* We must check at MOST one attribute to
-     set interrupt/exception/reset.  */
-  if (lookup_attribute ("interrupt", func_attrs))
-    intr_p = 1;
-  if (lookup_attribute ("exception", func_attrs))
-    excp_p = 1;
-  if (lookup_attribute ("reset", func_attrs))
-    reset_p = 1;
-
-  if ((intr_p + excp_p + reset_p) > 1)
-    error ("multiple interrupt attributes to function %qD", func_decl);
-}
-
-/* Function to construct isr vectors information array.
-   We DO NOT HAVE TO check if the attributes are valid
-   because those works are supposed to be done on
-   nds32_merge_decl_attributes() and nds32_insert_attributes().  */
-static void
-nds32_construct_isr_vectors_information (tree func_attrs,
-                                        const char *func_name)
-{
-  tree save_all, partial_save;
-  tree nested, not_nested, nested_ready;
-  tree intr, excp, reset;
-
-  save_all     = lookup_attribute ("save_all", func_attrs);
-  partial_save = lookup_attribute ("partial_save", func_attrs);
-
-  nested       = lookup_attribute ("nested", func_attrs);
-  not_nested   = lookup_attribute ("not_nested", func_attrs);
-  nested_ready = lookup_attribute ("nested_ready", func_attrs);
-
-  intr  = lookup_attribute ("interrupt", func_attrs);
-  excp  = lookup_attribute ("exception", func_attrs);
-  reset = lookup_attribute ("reset", func_attrs);
-
-  /* If there is no interrupt/exception/reset, we can return immediately.  */
-  if (!intr && !excp && !reset)
-    return;
-
-  /* If we are here, either we have interrupt/exception,
-     or reset attribute.  */
-  if (intr || excp)
-    {
-      tree id_list;
-
-      /* Prepare id list so that we can traverse and set vector id.  */
-      id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
-
-      while (id_list)
-       {
-         tree id;
-         int vector_id;
-         unsigned int vector_number_offset;
-
-         /* The way to handle interrupt or exception is the same,
-            we just need to take care of actual vector number.
-            For interrupt(0..63), the actual vector number is (9..72).
-            For exception(1..8), the actual vector number is (1..8).  */
-         vector_number_offset = (intr) ? (9) : (0);
-
-         /* Pick up each vector id value.  */
-         id = TREE_VALUE (id_list);
-         /* Add vector_number_offset to get actual vector number.  */
-         vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
-
-         /* Enable corresponding vector and set function name.  */
-         nds32_isr_vectors[vector_id].category = (intr)
-                                                 ? (NDS32_ISR_INTERRUPT)
-                                                 : (NDS32_ISR_EXCEPTION);
-         strcpy (nds32_isr_vectors[vector_id].func_name, func_name);
-
-         /* Set register saving scheme.  */
-         if (save_all)
-           nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL;
-         else if (partial_save)
-           nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE;
-
-         /* Set nested type.  */
-         if (nested)
-           nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED;
-         else if (not_nested)
-           nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
-         else if (nested_ready)
-           nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
-
-         /* Advance to next id.  */
-         id_list = TREE_CHAIN (id_list);
-       }
-    }
-  else
-    {
-      tree id_list;
-      tree id;
-      tree nmi, warm;
-
-      /* Deal with reset attribute.  Its vector number is always 0.  */
-      nds32_isr_vectors[0].category = NDS32_ISR_RESET;
-
-      /* Prepare id_list and identify id value so that
-         we can set total number of vectors.  */
-      id_list = TREE_VALUE (reset);
-      id = TREE_VALUE (id_list);
-
-      /* The total vectors = interrupt + exception numbers + reset.
-         There are 8 exception and 1 reset in nds32 architecture.  */
-      nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1;
-      strcpy (nds32_isr_vectors[0].func_name, func_name);
-
-      /* Retrieve nmi and warm function.  */
-      nmi  = lookup_attribute ("nmi", func_attrs);
-      warm = lookup_attribute ("warm", func_attrs);
-
-      if (nmi != NULL_TREE)
-       {
-         tree nmi_func_list;
-         tree nmi_func;
-
-         nmi_func_list = TREE_VALUE (nmi);
-         nmi_func = TREE_VALUE (nmi_func_list);
-
-         /* Record nmi function name.  */
-         strcpy (nds32_isr_vectors[0].nmi_name,
-                 IDENTIFIER_POINTER (nmi_func));
-       }
-
-      if (warm != NULL_TREE)
-       {
-         tree warm_func_list;
-         tree warm_func;
-
-         warm_func_list = TREE_VALUE (warm);
-         warm_func = TREE_VALUE (warm_func_list);
-
-         /* Record warm function name.  */
-         strcpy (nds32_isr_vectors[0].warm_name,
-                 IDENTIFIER_POINTER (warm_func));
-       }
-    }
-}
-
 /* Function that may creates more instructions
    for large value on adjusting stack pointer.
 
@@ -2655,8 +2201,6 @@ size_cost:
 static void
 nds32_asm_file_start (void)
 {
-  int i;
-
   default_file_start ();
 
   /* Tell assembler which ABI we are using.  */
@@ -2742,61 +2286,13 @@ nds32_asm_file_start (void)
 
   fprintf (asm_out_file, "\t! ------------------------------------\n");
 
-  /* Initialize isr vector information array before compiling functions.  */
-  for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
-    {
-      nds32_isr_vectors[i].category = NDS32_ISR_NONE;
-      strcpy (nds32_isr_vectors[i].func_name, "");
-      nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
-      nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
-      nds32_isr_vectors[i].total_n_vectors = 0;
-      strcpy (nds32_isr_vectors[i].nmi_name, "");
-      strcpy (nds32_isr_vectors[i].warm_name, "");
-    }
+  nds32_asm_file_start_for_isr ();
 }
 
 static void
 nds32_asm_file_end (void)
 {
-  int i;
-
-  /* If all the vectors are NDS32_ISR_NONE, we can return immediately.  */
-  for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
-    if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
-      break;
-
-  if (i == NDS32_N_ISR_VECTORS)
-    return;
-
-  /* At least one vector is NOT NDS32_ISR_NONE,
-     we should output isr vector information.  */
-  fprintf (asm_out_file, "\t! ------------------------------------\n");
-  fprintf (asm_out_file, "\t! The isr vector information:\n");
-  fprintf (asm_out_file, "\t! ------------------------------------\n");
-
-  /* Check reset handler first.  Its vector number is always 0.  */
-  if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
-    {
-      nds32_emit_isr_reset_content ();
-      fprintf (asm_out_file, "\t! ------------------------------------\n");
-    }
-
-  /* Check other vectors, starting from vector number 1.  */
-  for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
-    {
-      if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
-         || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
-       {
-         /* Found one vector which is interupt or exception.
-            Output its jmptbl and vector section content.  */
-         fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
-         fprintf (asm_out_file, "\t! ------------------------------------\n");
-         nds32_emit_isr_jmptbl_section (i);
-         fprintf (asm_out_file, "\t! ....................................\n");
-         nds32_emit_isr_vector_section (i);
-         fprintf (asm_out_file, "\t! ------------------------------------\n");
-       }
-    }
+  nds32_asm_file_end_for_isr ();
 
   fprintf (asm_out_file, "\t! ------------------------------------\n");
 }