Move ISR impelentation to nds32-isr.c module.
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
This commit is contained in:
parent
c0c935b507
commit
c23a919b86
@ -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>
|
||||
|
@ -17,3 +17,561 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -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);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -73,13 +73,6 @@
|
||||
/* 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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user