summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorChung-Ju Wu <jasonwucj@gmail.com>2018-08-12 07:38:40 +0000
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>2018-08-12 07:38:40 +0000
commita49317452416282f4cb4da0149754c58d87b2241 (patch)
tree7acf8d7580c0a7c12800740f68ef42e0a4f3cd91 /gcc/config
parent39d2c7ed9f6dd2d716b046bc28524bd26b3a9d46 (diff)
downloadgcc-a49317452416282f4cb4da0149754c58d87b2241.tar.gz
[NDS32] Implement more C ISR extension.
gcc/ * config.gcc (nds32*): Add nds32_isr.h and nds32_init.inc in extra_headers. * common/config/nds32/nds32-common.c (nds32_handle_option): Handle OPT_misr_secure_ case. * config/nds32/nds32-isr.c: Implementation of backward compatibility. * config/nds32/nds32-protos.h (nds32_isr_function_critical_p): New. * config/nds32/nds32.c (nds32_attribute_table): Add critical and secure attribute. * config/nds32/nds32.h (nds32_isr_nested_type): Add NDS32_CRITICAL. (nds32_isr_info): New field security_level. (TARGET_ISR_VECTOR_SIZE_4_BYTE): New macro. * config/nds32/nds32.md (return_internal): Consider critical attribute. * config/nds32/nds32.opt (misr-secure): New option. * config/nds32/nds32_init.inc: New file. * config/nds32/nds32_isr.h: New file. libgcc/ * config/nds32/t-nds32-isr: Rearrange object dependency. * config/nds32/initfini.c: Add dwarf2 unwinding support. * config/nds32/isr-library/adj_intr_lvl.inc: Consider new extensions and registers usage. * config/nds32/isr-library/excp_isr.S: Ditto. * config/nds32/isr-library/intr_isr.S: Ditto. * config/nds32/isr-library/reset.S: Ditto. * config/nds32/isr-library/restore_all.inc: Ditto. * config/nds32/isr-library/restore_mac_regs.inc: Ditto. * config/nds32/isr-library/restore_partial.inc: Ditto. * config/nds32/isr-library/restore_usr_regs.inc: Ditto. * config/nds32/isr-library/save_all.inc: Ditto. * config/nds32/isr-library/save_mac_regs.inc: Ditto. * config/nds32/isr-library/save_partial.inc: Ditto. * config/nds32/isr-library/save_usr_regs.inc: Ditto. * config/nds32/isr-library/vec_vid*.S: Consider 4-byte vector size. From-SVN: r263493
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/nds32/nds32-isr.c470
-rw-r--r--gcc/config/nds32/nds32-protos.h1
-rw-r--r--gcc/config/nds32/nds32.c58
-rw-r--r--gcc/config/nds32/nds32.h14
-rw-r--r--gcc/config/nds32/nds32.md11
-rw-r--r--gcc/config/nds32/nds32.opt4
-rw-r--r--gcc/config/nds32/nds32_init.inc43
-rw-r--r--gcc/config/nds32/nds32_isr.h526
8 files changed, 1092 insertions, 35 deletions
diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c
index 2c3aac7a256..db67a0e3666 100644
--- a/gcc/config/nds32/nds32-isr.c
+++ b/gcc/config/nds32/nds32-isr.c
@@ -43,7 +43,260 @@
We use an array to record essential information for each vector. */
static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
-/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------- */
+/* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ We provide several functions to parse the strings. */
+
+static void
+nds32_interrupt_attribute_parse_string (const char *original_str,
+ const char *func_name,
+ unsigned int s_level)
+{
+ char target_str[100];
+ enum nds32_isr_save_reg save_reg;
+ enum nds32_isr_nested_type nested_type;
+
+ char *save_all_regs_str, *save_caller_regs_str;
+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str;
+ char *id_str, *value_str;
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+
+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL
+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */
+ save_all_regs_str = strstr (target_str, "save_all_regs");
+ save_caller_regs_str = strstr (target_str, "save_caller_regs");
+
+ /* Note that if no argument is found,
+ use NDS32_PARTIAL_SAVE by default. */
+ if (save_all_regs_str)
+ save_reg = NDS32_SAVE_ALL;
+ else if (save_caller_regs_str)
+ save_reg = NDS32_PARTIAL_SAVE;
+ else
+ save_reg = NDS32_PARTIAL_SAVE;
+
+ /* 2. Detect 'nested' : NDS32_NESTED
+ 'not_nested' : NDS32_NOT_NESTED
+ 'ready_nested' : NDS32_NESTED_READY
+ 'critical' : NDS32_CRITICAL */
+ nested_str = strstr (target_str, "nested");
+ not_nested_str = strstr (target_str, "not_nested");
+ ready_nested_str = strstr (target_str, "ready_nested");
+ critical_str = strstr (target_str, "critical");
+
+ /* Note that if no argument is found,
+ use NDS32_NOT_NESTED by default.
+ Also, since 'not_nested' and 'ready_nested' both contains
+ 'nested' string, we check 'nested' with lowest priority. */
+ if (not_nested_str)
+ nested_type = NDS32_NOT_NESTED;
+ else if (ready_nested_str)
+ nested_type = NDS32_NESTED_READY;
+ else if (nested_str)
+ nested_type = NDS32_NESTED;
+ else if (critical_str)
+ nested_type = NDS32_CRITICAL;
+ else
+ nested_type = NDS32_NOT_NESTED;
+
+ /* 3. Traverse each id value and set corresponding information. */
+ id_str = strstr (target_str, "id=");
+
+ /* If user forgets to assign 'id', issue an error message. */
+ if (id_str == NULL)
+ error ("require id argument in the string");
+ /* Extract the value_str first. */
+ id_str = strtok (id_str, "=");
+ value_str = strtok (NULL, ";");
+
+ /* Pick up the first id value token. */
+ value_str = strtok (value_str, ",");
+ while (value_str != NULL)
+ {
+ int i;
+ i = atoi (value_str);
+
+ /* For interrupt(0..63), the actual vector number is (9..72). */
+ i = i + 9;
+ if (i < 9 || i > 72)
+ error ("invalid id value for interrupt attribute");
+
+ /* Setup nds32_isr_vectors[] array. */
+ nds32_isr_vectors[i].category = NDS32_ISR_INTERRUPT;
+ strcpy (nds32_isr_vectors[i].func_name, func_name);
+ nds32_isr_vectors[i].save_reg = save_reg;
+ nds32_isr_vectors[i].nested_type = nested_type;
+ nds32_isr_vectors[i].security_level = s_level;
+
+ /* Fetch next token. */
+ value_str = strtok (NULL, ",");
+ }
+
+ return;
+}
+
+static void
+nds32_exception_attribute_parse_string (const char *original_str,
+ const char *func_name,
+ unsigned int s_level)
+{
+ char target_str[100];
+ enum nds32_isr_save_reg save_reg;
+ enum nds32_isr_nested_type nested_type;
+
+ char *save_all_regs_str, *save_caller_regs_str;
+ char *nested_str, *not_nested_str, *ready_nested_str, *critical_str;
+ char *id_str, *value_str;
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+
+ /* 1. Detect 'save_all_regs' : NDS32_SAVE_ALL
+ 'save_caller_regs' : NDS32_PARTIAL_SAVE */
+ save_all_regs_str = strstr (target_str, "save_all_regs");
+ save_caller_regs_str = strstr (target_str, "save_caller_regs");
+
+ /* Note that if no argument is found,
+ use NDS32_PARTIAL_SAVE by default. */
+ if (save_all_regs_str)
+ save_reg = NDS32_SAVE_ALL;
+ else if (save_caller_regs_str)
+ save_reg = NDS32_PARTIAL_SAVE;
+ else
+ save_reg = NDS32_PARTIAL_SAVE;
+
+ /* 2. Detect 'nested' : NDS32_NESTED
+ 'not_nested' : NDS32_NOT_NESTED
+ 'ready_nested' : NDS32_NESTED_READY
+ 'critical' : NDS32_CRITICAL */
+ nested_str = strstr (target_str, "nested");
+ not_nested_str = strstr (target_str, "not_nested");
+ ready_nested_str = strstr (target_str, "ready_nested");
+ critical_str = strstr (target_str, "critical");
+
+ /* Note that if no argument is found,
+ use NDS32_NOT_NESTED by default.
+ Also, since 'not_nested' and 'ready_nested' both contains
+ 'nested' string, we check 'nested' with lowest priority. */
+ if (not_nested_str)
+ nested_type = NDS32_NOT_NESTED;
+ else if (ready_nested_str)
+ nested_type = NDS32_NESTED_READY;
+ else if (nested_str)
+ nested_type = NDS32_NESTED;
+ else if (critical_str)
+ nested_type = NDS32_CRITICAL;
+ else
+ nested_type = NDS32_NOT_NESTED;
+
+ /* 3. Traverse each id value and set corresponding information. */
+ id_str = strstr (target_str, "id=");
+
+ /* If user forgets to assign 'id', issue an error message. */
+ if (id_str == NULL)
+ error ("require id argument in the string");
+ /* Extract the value_str first. */
+ id_str = strtok (id_str, "=");
+ value_str = strtok (NULL, ";");
+
+ /* Pick up the first id value token. */
+ value_str = strtok (value_str, ",");
+ while (value_str != NULL)
+ {
+ int i;
+ i = atoi (value_str);
+
+ /* For exception(1..8), the actual vector number is (1..8). */
+ if (i < 1 || i > 8)
+ error ("invalid id value for exception attribute");
+
+ /* Setup nds32_isr_vectors[] array. */
+ nds32_isr_vectors[i].category = NDS32_ISR_EXCEPTION;
+ strcpy (nds32_isr_vectors[i].func_name, func_name);
+ nds32_isr_vectors[i].save_reg = save_reg;
+ nds32_isr_vectors[i].nested_type = nested_type;
+ nds32_isr_vectors[i].security_level = s_level;
+
+ /* Fetch next token. */
+ value_str = strtok (NULL, ",");
+ }
+
+ return;
+}
+
+static void
+nds32_reset_attribute_parse_string (const char *original_str,
+ const char *func_name)
+{
+ char target_str[100];
+ char *vectors_str, *nmi_str, *warm_str, *value_str;
+
+ /* Deal with reset attribute. Its vector number is always 0. */
+ nds32_isr_vectors[0].category = NDS32_ISR_RESET;
+
+
+ /* 1. Parse 'vectors=XXXX'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ vectors_str = strstr (target_str, "vectors=");
+ /* The total vectors = interrupt + exception numbers + reset.
+ There are 8 exception and 1 reset in nds32 architecture.
+ If user forgets to assign 'vectors', user default 16 interrupts. */
+ if (vectors_str != NULL)
+ {
+ /* Extract the value_str. */
+ vectors_str = strtok (vectors_str, "=");
+ value_str = strtok (NULL, ";");
+ nds32_isr_vectors[0].total_n_vectors = atoi (value_str) + 8 + 1;
+ }
+ else
+ nds32_isr_vectors[0].total_n_vectors = 16 + 8 + 1;
+ strcpy (nds32_isr_vectors[0].func_name, func_name);
+
+
+ /* 2. Parse 'nmi_func=YYYY'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ nmi_str = strstr (target_str, "nmi_func=");
+ if (nmi_str != NULL)
+ {
+ /* Extract the value_str. */
+ nmi_str = strtok (nmi_str, "=");
+ value_str = strtok (NULL, ";");
+ strcpy (nds32_isr_vectors[0].nmi_name, value_str);
+ }
+
+ /* 3. Parse 'warm_func=ZZZZ'. */
+
+ /* Copy original string into a character array so that
+ the string APIs can handle it. */
+ strcpy (target_str, original_str);
+ warm_str = strstr (target_str, "warm_func=");
+ if (warm_str != NULL)
+ {
+ /* Extract the value_str. */
+ warm_str = strtok (warm_str, "=");
+ value_str = strtok (NULL, ";");
+ strcpy (nds32_isr_vectors[0].warm_name, value_str);
+ }
+
+ return;
+}
+/* ------------------------------------------------------------- */
/* A helper function to emit section head template. */
static void
@@ -79,6 +332,15 @@ nds32_emit_isr_jmptbl_section (int vector_id)
char section_name[100];
char symbol_name[100];
+ /* A critical isr does not need jump table section because
+ its behavior is not performed by two-level handler. */
+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL)
+ {
+ fprintf (asm_out_file, "\t! The vector %02d is a critical isr !\n",
+ vector_id);
+ return;
+ }
+
/* Prepare jmptbl section and symbol name. */
snprintf (section_name, sizeof (section_name),
".nds32_jmptbl.%02d", vector_id);
@@ -99,7 +361,6 @@ nds32_emit_isr_vector_section (int vector_id)
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];
@@ -147,30 +408,47 @@ nds32_emit_isr_vector_section (int vector_id)
case NDS32_NESTED_READY:
nt_str = "nr";
break;
+ case NDS32_CRITICAL:
+ /* The critical isr is not performed by two-level handler. */
+ nt_str = "";
+ 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);
+ if (nds32_isr_vectors[vector_id].security_level == 0)
+ {
+ /* For security level 0, use normal first level handler name. */
+ snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+ "_nds32_%s_%s_%s", c_str, sr_str, nt_str);
+ }
+ else
+ {
+ /* For security level 1-3, use corresponding spl_1, spl_2, or spl_3. */
+ snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+ "_nds32_spl_%d", nds32_isr_vectors[vector_id].security_level);
+ }
/* 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);
+ "_nds32_vector_%02d", vector_id);
/* 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)
+ /* First we check if it is a critical isr.
+ If so, jump to user handler directly; otherwise, the instructions
+ in the vector section may be different according to the vector size. */
+ if (nds32_isr_vectors[vector_id].nested_type == NDS32_CRITICAL)
+ {
+ /* This block is for critical isr. Jump to user handler directly. */
+ fprintf (asm_out_file, "\tj\t%s ! jump to user handler directly\n",
+ nds32_isr_vectors[vector_id].func_name);
+ }
+ else if (nds32_isr_vector_size == 4)
{
/* This block is for 4-byte vector size.
Hardware $VID support is necessary and only one instruction
@@ -239,13 +517,11 @@ 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");
@@ -261,7 +537,7 @@ nds32_emit_isr_reset_content (void)
/* 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);
+ fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d\n", i);
/* Emit jmptbl_00 section. */
snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
@@ -275,9 +551,9 @@ nds32_emit_isr_reset_content (void)
/* 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 (symbol_name, sizeof (symbol_name), "_nds32_vector_00");
snprintf (reset_handler_name, sizeof (reset_handler_name),
- "_nds32_reset%s", vs_str);
+ "_nds32_reset");
fprintf (asm_out_file, "\t! ....................................\n");
nds32_emit_section_head_template (section_name, symbol_name,
@@ -323,12 +599,12 @@ 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 nested_p, not_nested_p, nested_ready_p, critical_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;
+ nested_p = not_nested_p = nested_ready_p = critical_p = 0;
intr_p = excp_p = reset_p = 0;
/* We must check at MOST one attribute to set save-reg. */
@@ -347,8 +623,10 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
not_nested_p = 1;
if (lookup_attribute ("nested_ready", func_attrs))
nested_ready_p = 1;
+ if (lookup_attribute ("critical", func_attrs))
+ critical_p = 1;
- if ((nested_p + not_nested_p + nested_ready_p) > 1)
+ if ((nested_p + not_nested_p + nested_ready_p + critical_p) > 1)
error ("multiple nested types attributes to function %qD", func_decl);
/* We must check at MOST one attribute to
@@ -362,6 +640,17 @@ nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
if ((intr_p + excp_p + reset_p) > 1)
error ("multiple interrupt attributes to function %qD", func_decl);
+
+ /* Do not allow isr attributes under linux toolchain. */
+ if (TARGET_LINUX_ABI && intr_p)
+ error ("cannot use interrupt attributes to function %qD "
+ "under linux toolchain", func_decl);
+ if (TARGET_LINUX_ABI && excp_p)
+ error ("cannot use exception attributes to function %qD "
+ "under linux toolchain", func_decl);
+ if (TARGET_LINUX_ABI && reset_p)
+ error ("cannot use reset attributes to function %qD "
+ "under linux toolchain", func_decl);
}
/* Function to construct isr vectors information array.
@@ -373,15 +662,21 @@ nds32_construct_isr_vectors_information (tree func_attrs,
const char *func_name)
{
tree save_all, partial_save;
- tree nested, not_nested, nested_ready;
+ tree nested, not_nested, nested_ready, critical;
tree intr, excp, reset;
+ tree secure;
+ tree security_level_list;
+ tree security_level;
+ unsigned int s_level;
+
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);
+ critical = lookup_attribute ("critical", func_attrs);
intr = lookup_attribute ("interrupt", func_attrs);
excp = lookup_attribute ("exception", func_attrs);
@@ -391,6 +686,63 @@ nds32_construct_isr_vectors_information (tree func_attrs,
if (!intr && !excp && !reset)
return;
+ /* At first, we need to retrieve security level. */
+ secure = lookup_attribute ("secure", func_attrs);
+ if (secure != NULL)
+ {
+ security_level_list = TREE_VALUE (secure);
+ security_level = TREE_VALUE (security_level_list);
+ s_level = TREE_INT_CST_LOW (security_level);
+ }
+ else
+ {
+ /* If there is no secure attribute, the security level is set by
+ nds32_isr_secure_level, which is controlled by -misr-secure=X option.
+ By default nds32_isr_secure_level should be 0. */
+ s_level = nds32_isr_secure_level;
+ }
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ If interrupt/exception/reset appears and its argument is a
+ STRING_CST, we will parse string with some auxiliary functions
+ which set necessary isr information in the nds32_isr_vectors[] array.
+ After that, we can return immediately to avoid new-syntax isr
+ information construction. */
+ if (intr != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (intr));
+ nds32_interrupt_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name,
+ s_level);
+ return;
+ }
+ if (excp != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (excp));
+ nds32_exception_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name,
+ s_level);
+ return;
+ }
+ if (reset != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST)
+ {
+ tree string_arg = TREE_VALUE (TREE_VALUE (reset));
+ nds32_reset_attribute_parse_string (TREE_STRING_POINTER (string_arg),
+ func_name);
+ return;
+ }
+ /* ------------------------------------------------------------- */
+
/* If we are here, either we have interrupt/exception,
or reset attribute. */
if (intr || excp)
@@ -417,6 +769,9 @@ nds32_construct_isr_vectors_information (tree func_attrs,
/* Add vector_number_offset to get actual vector number. */
vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
+ /* Set security level. */
+ nds32_isr_vectors[vector_id].security_level = s_level;
+
/* Enable corresponding vector and set function name. */
nds32_isr_vectors[vector_id].category = (intr)
? (NDS32_ISR_INTERRUPT)
@@ -436,6 +791,8 @@ nds32_construct_isr_vectors_information (tree func_attrs,
nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
else if (nested_ready)
nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
+ else if (critical)
+ nds32_isr_vectors[vector_id].nested_type = NDS32_CRITICAL;
/* Advance to next id. */
id_list = TREE_CHAIN (id_list);
@@ -492,7 +849,6 @@ nds32_construct_isr_vectors_information (tree func_attrs,
}
}
-/* A helper function to handle isr stuff at the beginning of asm file. */
void
nds32_asm_file_start_for_isr (void)
{
@@ -505,15 +861,14 @@ nds32_asm_file_start_for_isr (void)
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].security_level = 0;
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)
+void nds32_asm_file_end_for_isr (void)
{
int i;
@@ -547,6 +902,8 @@ nds32_asm_file_end_for_isr (void)
/* 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! security level: %d\n",
+ nds32_isr_vectors[i].security_level);
fprintf (asm_out_file, "\t! ------------------------------------\n");
nds32_emit_isr_jmptbl_section (i);
fprintf (asm_out_file, "\t! ....................................\n");
@@ -580,4 +937,65 @@ nds32_isr_function_p (tree func)
|| (t_reset != NULL_TREE));
}
-/* ------------------------------------------------------------------------ */
+/* Return true if FUNC is a isr function with critical attribute. */
+bool
+nds32_isr_function_critical_p (tree func)
+{
+ tree t_intr;
+ tree t_excp;
+ tree t_critical;
+
+ tree attrs;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ abort ();
+
+ attrs = DECL_ATTRIBUTES (func);
+
+ t_intr = lookup_attribute ("interrupt", attrs);
+ t_excp = lookup_attribute ("exception", attrs);
+
+ t_critical = lookup_attribute ("critical", attrs);
+
+ /* If both interrupt and exception attribute does not appear,
+ we can return false immediately. */
+ if ((t_intr == NULL_TREE) && (t_excp == NULL_TREE))
+ return false;
+
+ /* Here we can guarantee either interrupt or ecxception attribute
+ does exist, so further check critical attribute.
+ If it also appears, we can return true. */
+ if (t_critical != NULL_TREE)
+ return true;
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to handle string type.
+ If the string 'critical' appears in the interrupt/exception
+ string argument, we can return true. */
+ if (t_intr != NULL_TREE || t_excp != NULL_TREE)
+ {
+ char target_str[100];
+ char *critical_str;
+ tree t_check;
+ tree string_arg;
+
+ t_check = t_intr ? t_intr : t_excp;
+ if (TREE_CODE (TREE_VALUE (TREE_VALUE (t_check))) == STRING_CST)
+ {
+ string_arg = TREE_VALUE (TREE_VALUE (t_check));
+ strcpy (target_str, TREE_STRING_POINTER (string_arg));
+ critical_str = strstr (target_str, "critical");
+
+ /* Found 'critical' string, so return true. */
+ if (critical_str)
+ return true;
+ }
+ }
+ /* ------------------------------------------------------------- */
+
+ /* Other cases, this isr function is not critical type. */
+ return false;
+}
+
+/* ------------------------------------------------------------- */
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 3fa8ae175f2..5c4d233b4b9 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -307,6 +307,7 @@ 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);
extern bool nds32_isr_function_p (tree);
+extern bool nds32_isr_function_critical_p (tree);
/* Auxiliary functions for cost calculation. */
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 721135e6ba1..f68341e1fcd 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -305,6 +305,7 @@ static const struct attribute_spec nds32_attribute_table[] =
{ "nested", 0, 0, false, false, false, false, NULL, NULL },
{ "not_nested", 0, 0, false, false, false, false, NULL, NULL },
{ "nested_ready", 0, 0, false, false, false, false, NULL, NULL },
+ { "critical", 0, 0, false, false, false, false, NULL, NULL },
/* The attributes describing isr register save scheme. */
{ "save_all", 0, 0, false, false, false, false, NULL, NULL },
@@ -314,6 +315,9 @@ static const struct attribute_spec nds32_attribute_table[] =
{ "nmi", 1, 1, false, false, false, false, NULL, NULL },
{ "warm", 1, 1, false, false, false, false, NULL, NULL },
+ /* The attributes describing isr security level. */
+ { "secure", 1, 1, false, false, false, false, NULL, NULL },
+
/* The attribute telling no prologue/epilogue. */
{ "naked", 0, 0, false, false, false, false, NULL, NULL },
@@ -518,7 +522,7 @@ nds32_compute_stack_frame (void)
}
/* Check if this function can omit prologue/epilogue code fragment.
- If there is 'no_prologue'/'naked' attribute in this function,
+ If there is 'no_prologue'/'naked'/'secure' attribute in this function,
we can set 'naked_p' flag to indicate that
we do not have to generate prologue/epilogue.
Or, if all the following conditions succeed,
@@ -533,6 +537,7 @@ nds32_compute_stack_frame (void)
we do not need to adjust $sp. */
if (lookup_attribute ("no_prologue", DECL_ATTRIBUTES (current_function_decl))
|| lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
+ || lookup_attribute ("secure", DECL_ATTRIBUTES (current_function_decl))
|| (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM
&& cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM
@@ -2307,14 +2312,17 @@ nds32_function_ok_for_sibcall (tree decl,
/* 1. Do not apply sibling call if -mv3push is enabled,
because pop25 instruction also represents return behavior.
- 2. If this function is a variadic function, do not apply sibling call
+ 2. If this function is a isr function, do not apply sibling call
+ because it may perform the behavior that user does not expect.
+ 3. If this function is a variadic function, do not apply sibling call
because the stack layout may be a mess.
- 3. We don't want to apply sibling call optimization for indirect
+ 4. We don't want to apply sibling call optimization for indirect
sibcall because the pop behavior in epilogue may pollute the
content of caller-saved regsiter when the register is used for
indirect sibcall.
- 4. In pic mode, it may use some registers for PLT call. */
+ 5. In pic mode, it may use some registers for PLT call. */
return (!TARGET_V3PUSH
+ && !nds32_isr_function_p (current_function_decl)
&& (cfun->machine->va_args_size == 0)
&& decl
&& !flag_pic);
@@ -3968,6 +3976,38 @@ nds32_insert_attributes (tree decl, tree *attributes)
excp = lookup_attribute ("exception", func_attrs);
reset = lookup_attribute ("reset", func_attrs);
+ /* The following code may use attribute arguments. If there is no
+ argument from source code, it will cause segmentation fault.
+ Therefore, return dircetly and report error message later. */
+ if ((intr && TREE_VALUE (intr) == NULL)
+ || (excp && TREE_VALUE (excp) == NULL)
+ || (reset && TREE_VALUE (reset) == NULL))
+ return;
+
+ /* ------------------------------------------------------------- */
+ /* FIXME:
+ FOR BACKWARD COMPATIBILITY, we need to support following patterns:
+
+ __attribute__((interrupt("XXX;YYY;id=ZZZ")))
+ __attribute__((exception("XXX;YYY;id=ZZZ")))
+ __attribute__((reset("vectors=XXX;nmi_func=YYY;warm_func=ZZZ")))
+
+ If interrupt/exception/reset appears and its argument is a
+ STRING_CST, we will use other functions to parse string in the
+ nds32_construct_isr_vectors_information() and then set necessary
+ isr information in the nds32_isr_vectors[] array. Here we can
+ just return immediately to avoid new-syntax checking. */
+ if (intr != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (intr))) == STRING_CST)
+ return;
+ if (excp != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (excp))) == STRING_CST)
+ return;
+ if (reset != NULL_TREE
+ && TREE_CODE (TREE_VALUE (TREE_VALUE (reset))) == STRING_CST)
+ return;
+ /* ------------------------------------------------------------- */
+
if (intr || excp)
{
/* Deal with interrupt/exception. */
@@ -4211,6 +4251,16 @@ nds32_cpu_cpp_builtins(struct cpp_reader *pfile)
builtin_define ("__nds32__");
builtin_define ("__NDS32__");
+ /* We need to provide builtin macro to describe the size of
+ each vector for interrupt handler under elf toolchain. */
+ if (!TARGET_LINUX_ABI)
+ {
+ if (TARGET_ISR_VECTOR_SIZE_4_BYTE)
+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_4__");
+ else
+ builtin_define ("__NDS32_ISR_VECTOR_SIZE_16__");
+ }
+
if (TARGET_HARD_FLOAT)
builtin_define ("__NDS32_ABI_2FP_PLUS__");
else
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
index 3aac6a21bb8..cec15bed8ca 100644
--- a/gcc/config/nds32/nds32.h
+++ b/gcc/config/nds32/nds32.h
@@ -367,7 +367,8 @@ enum nds32_isr_nested_type
{
NDS32_NESTED,
NDS32_NOT_NESTED,
- NDS32_NESTED_READY
+ NDS32_NESTED_READY,
+ NDS32_CRITICAL
};
/* Define structure to record isr information.
@@ -395,6 +396,13 @@ struct nds32_isr_info
unless user specifies attribute to change it. */
enum nds32_isr_nested_type nested_type;
+ /* Secure isr level.
+ Currently we have 0-3 security level.
+ It should be set to 0 by default.
+ For security processors, this is determined by secure
+ attribute or compiler options. */
+ unsigned int security_level;
+
/* Total vectors.
The total vectors = interrupt + exception numbers + reset.
It should be set to 0 by default.
@@ -849,8 +857,10 @@ enum nds32_builtins
/* ------------------------------------------------------------------------ */
-#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
+#define TARGET_ISR_VECTOR_SIZE_4_BYTE \
+ (nds32_isr_vector_size == 4)
+#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
#define TARGET_ISA_V3 \
(nds32_arch_option == ARCH_V3 \
|| nds32_arch_option == ARCH_V3J \
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index 92e90dda1af..f5349d7cc76 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -1993,6 +1993,9 @@
[(simple_return)]
""
{
+ if (nds32_isr_function_critical_p (current_function_decl))
+ return "iret";
+
if (TARGET_16_BIT)
return "ret5";
else
@@ -2001,9 +2004,11 @@
[(set_attr "type" "branch")
(set_attr "enabled" "yes")
(set (attr "length")
- (if_then_else (match_test "TARGET_16_BIT")
- (const_int 2)
- (const_int 4)))])
+ (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)")
+ (const_int 4)
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4))))])
;; ----------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt
index a9ffae1ea6c..d73f5af9dbc 100644
--- a/gcc/config/nds32/nds32.opt
+++ b/gcc/config/nds32/nds32.opt
@@ -158,6 +158,10 @@ misr-vector-size=
Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE)
Specify the size of each interrupt vector, which must be 4 or 16.
+misr-secure=
+Target RejectNegative Joined UInteger Var(nds32_isr_secure_level) Init(0)
+Specify the security level of c-isr for the whole file.
+
mcache-block-size=
Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE)
Specify the size of each cache block, which must be a power of 2 between 4 and 512.
diff --git a/gcc/config/nds32/nds32_init.inc b/gcc/config/nds32/nds32_init.inc
new file mode 100644
index 00000000000..1084ad0e471
--- /dev/null
+++ b/gcc/config/nds32/nds32_init.inc
@@ -0,0 +1,43 @@
+/*
+ * nds32_init.inc
+ *
+ * NDS32 architecture startup assembler header file
+ *
+ */
+
+.macro nds32_init
+
+ ! Initialize GP for data access
+ la $gp, _SDA_BASE_
+
+#if defined(__NDS32_EXT_EX9__)
+ ! Check HW for EX9
+ mfsr $r0, $MSC_CFG
+ li $r1, (1 << 24)
+ and $r2, $r0, $r1
+ beqz $r2, 1f
+
+ ! Initialize the table base of EX9 instruction
+ la $r0, _ITB_BASE_
+ mtusr $r0, $ITB
+1:
+#endif
+
+#if defined(__NDS32_EXT_FPU_DP__) || defined(__NDS32_EXT_FPU_SP__)
+ ! Enable FPU
+ mfsr $r0, $FUCOP_CTL
+ ori $r0, $r0, #0x1
+ mtsr $r0, $FUCOP_CTL
+ dsb
+
+ ! Enable denormalized flush-to-Zero mode
+ fmfcsr $r0
+ ori $r0,$r0,#0x1000
+ fmtcsr $r0
+ dsb
+#endif
+
+ ! Initialize default stack pointer
+ la $sp, _stack
+
+.endm
diff --git a/gcc/config/nds32/nds32_isr.h b/gcc/config/nds32/nds32_isr.h
new file mode 100644
index 00000000000..8ea58f951e1
--- /dev/null
+++ b/gcc/config/nds32/nds32_isr.h
@@ -0,0 +1,526 @@
+/* Intrinsic definitions of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _NDS32_ISR_H
+#define _NDS32_ISR_H
+
+/* Attribute of a interrupt or exception handler:
+
+ NDS32_READY_NESTED: This handler is interruptible if user re-enable GIE bit.
+ NDS32_NESTED : This handler is interruptible. This is not suitable
+ exception handler.
+ NDS32_NOT_NESTED : This handler is NOT interruptible. Users have to do
+ some work if nested is wanted
+ NDS32_CRITICAL : This handler is critical ISR, which means it is small
+ and efficient. */
+#define NDS32_READY_NESTED 0
+#define NDS32_NESTED 1
+#define NDS32_NOT_NESTED 2
+#define NDS32_CRITICAL 3
+
+/* Attribute of a interrupt or exception handler:
+
+ NDS32_SAVE_ALL_REGS : Save all registers in a table.
+ NDS32_SAVE_PARTIAL_REGS: Save partial registers. */
+#define NDS32_SAVE_CALLER_REGS 0
+#define NDS32_SAVE_ALL_REGS 1
+
+/* There are two version of Register table for interrupt and exception handler,
+ one for 16-register CPU the other for 32-register CPU. These structures are
+ used for context switching or system call handling. The address of this
+ data can be get from the input argument of the handler functions.
+
+ For system call handling, r0 to r5 are used to pass arguments. If more
+ arguments are used they are put into the stack and its starting address is
+ in sp. Return value of system call can be put into r0 and r1 upon exit from
+ system call handler. System call ID is in a system register and it can be
+ fetched via intrinsic function. For more information please read ABI and
+ other related documents.
+
+ For context switching, at least 2 values need to saved in kernel. One is
+ IPC and the other is the stack address of current task. Use intrinsic
+ function to get IPC and the input argument of the handler functions + 8 to
+ get stack address of current task. To do context switching, you replace
+ new_sp with the stack address of new task and replace IPC system register
+ with IPC of new task, then, just return from handler. The context switching
+ will happen. */
+
+/* Register table for exception handler; 32-register version. */
+typedef struct
+{
+ int r0;
+ int r1;
+ int r2;
+ int r3;
+ int r4;
+ int r5;
+ int r6;
+ int r7;
+ int r8;
+ int r9;
+ int r10;
+ int r11;
+ int r12;
+ int r13;
+ int r14;
+ int r15;
+ int r16;
+ int r17;
+ int r18;
+ int r19;
+ int r20;
+ int r21;
+ int r22;
+ int r23;
+ int r24;
+ int r25;
+ int r26;
+ int r27;
+ int fp;
+ int gp;
+ int lp;
+ int sp;
+} NDS32_GPR32;
+
+/* Register table for exception handler; 16-register version. */
+typedef struct
+{
+ int r0;
+ int r1;
+ int r2;
+ int r3;
+ int r4;
+ int r5;
+ int r6;
+ int r7;
+ int r8;
+ int r9;
+ int r10;
+ int r15;
+ int fp;
+ int gp;
+ int lp;
+ int sp;
+} NDS32_GPR16;
+
+
+/* Use NDS32_REG32_TAB or NDS32_REG16_TAB in your program to
+ access register table. */
+typedef struct
+{
+ union
+ {
+ int reg_a[32] ;
+ NDS32_GPR32 reg_s ;
+ } u ;
+} NDS32_REG32_TAB;
+
+typedef struct
+{
+ union
+ {
+ int reg_a[16] ;
+ NDS32_GPR16 reg_s ;
+ } u ;
+} NDS32_REG16_TAB;
+
+typedef struct
+{
+ int d0lo;
+ int d0hi;
+ int d1lo;
+ int d1hi;
+} NDS32_DX_TAB;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+#endif
+} NDS32_FSR8;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+} NDS32_DSR4;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+ float fsr8;
+ float fsr9;
+ float fsr10;
+ float fsr11;
+ float fsr12;
+ float fsr13;
+ float fsr14;
+ float fsr15;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+ float fsr9;
+ float fsr8;
+ float fsr11;
+ float fsr10;
+ float fsr13;
+ float fsr12;
+ float fsr15;
+ float fsr14;
+#endif
+} NDS32_FSR16;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+} NDS32_DSR8;
+
+typedef struct
+{
+#ifdef __NDS32_EB__
+ float fsr0;
+ float fsr1;
+ float fsr2;
+ float fsr3;
+ float fsr4;
+ float fsr5;
+ float fsr6;
+ float fsr7;
+ float fsr8;
+ float fsr9;
+ float fsr10;
+ float fsr11;
+ float fsr12;
+ float fsr13;
+ float fsr14;
+ float fsr15;
+ float fsr16;
+ float fsr17;
+ float fsr18;
+ float fsr19;
+ float fsr20;
+ float fsr21;
+ float fsr22;
+ float fsr23;
+ float fsr24;
+ float fsr25;
+ float fsr26;
+ float fsr27;
+ float fsr28;
+ float fsr29;
+ float fsr30;
+ float fsr31;
+#else
+ float fsr1;
+ float fsr0;
+ float fsr3;
+ float fsr2;
+ float fsr5;
+ float fsr4;
+ float fsr7;
+ float fsr6;
+ float fsr9;
+ float fsr8;
+ float fsr11;
+ float fsr10;
+ float fsr13;
+ float fsr12;
+ float fsr15;
+ float fsr14;
+ float fsr17;
+ float fsr16;
+ float fsr19;
+ float fsr18;
+ float fsr21;
+ float fsr20;
+ float fsr23;
+ float fsr22;
+ float fsr25;
+ float fsr24;
+ float fsr27;
+ float fsr26;
+ float fsr29;
+ float fsr28;
+ float fsr31;
+ float fsr30;
+#endif
+} NDS32_FSR32;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+ double dsr8;
+ double dsr9;
+ double dsr10;
+ double dsr11;
+ double dsr12;
+ double dsr13;
+ double dsr14;
+ double dsr15;
+} NDS32_DSR16;
+
+typedef struct
+{
+ double dsr0;
+ double dsr1;
+ double dsr2;
+ double dsr3;
+ double dsr4;
+ double dsr5;
+ double dsr6;
+ double dsr7;
+ double dsr8;
+ double dsr9;
+ double dsr10;
+ double dsr11;
+ double dsr12;
+ double dsr13;
+ double dsr14;
+ double dsr15;
+ double dsr16;
+ double dsr17;
+ double dsr18;
+ double dsr19;
+ double dsr20;
+ double dsr21;
+ double dsr22;
+ double dsr23;
+ double dsr24;
+ double dsr25;
+ double dsr26;
+ double dsr27;
+ double dsr28;
+ double dsr29;
+ double dsr30;
+ double dsr31;
+} NDS32_DSR32;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR8 fsr_s ;
+ NDS32_DSR4 dsr_s ;
+ } u ;
+} NDS32_FPU8_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR16 fsr_s ;
+ NDS32_DSR8 dsr_s ;
+ } u ;
+} NDS32_FPU16_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR32 fsr_s ;
+ NDS32_DSR16 dsr_s ;
+ } u ;
+} NDS32_FPU32_TAB;
+
+typedef struct
+{
+ union
+ {
+ NDS32_FSR32 fsr_s ;
+ NDS32_DSR32 dsr_s ;
+ } u ;
+} NDS32_FPU64_TAB;
+
+typedef struct
+{
+ int ipc;
+ int ipsw;
+#if defined(NDS32_EXT_FPU_CONFIG_0)
+ NDS32_FPU8_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_1)
+ NDS32_FPU16_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_2)
+ NDS32_FPU32_TAB fpr;
+#elif defined(NDS32_EXT_FPU_CONFIG_3)
+ NDS32_FPU64_TAB fpr;
+#endif
+#if __NDS32_DX_REGS__
+ NDS32_DX_TAB dxr;
+#endif
+#if __NDS32_EXT_IFC__
+ int ifc_lp;
+ int filler;
+#endif
+#if __NDS32_REDUCED_REGS__ || __NDS32_REDUCE_REGS
+ NDS32_REG16_TAB gpr;
+#else
+ NDS32_REG32_TAB gpr;
+#endif
+} NDS32_CONTEXT;
+
+/* Predefined Vector Definition.
+
+ For IVIC Mode: 9 to 14 are for hardware interrupt
+ and 15 is for software interrupt.
+ For EVIC Mode: 9 to 72 are for hardware interrupt
+ and software interrupt can be routed to any one of them.
+
+ You may want to define your hardware interrupts in the following way
+ for easy maintainance.
+
+ IVIC mode:
+ #define MY_HW_IVIC_TIMER NDS32_VECTOR_INTERRUPT_HW0 + 1
+ #define MY_HW_IVIC_USB NDS32_VECTOR_INTERRUPT_HW0 + 3
+ EVIC mode:
+ #define MY_HW_EVIC_DMA NDS32_VECTOR_INTERRUPT_HW0 + 2
+ #define MY_HW_EVIC_SWI NDS32_VECTOR_INTERRUPT_HW0 + 10 */
+#define NDS32_VECTOR_RESET 0
+#define NDS32_VECTOR_TLB_FILL 1
+#define NDS32_VECTOR_PTE_NOT_PRESENT 2
+#define NDS32_VECTOR_TLB_MISC 3
+#define NDS32_VECTOR_TLB_VLPT_MISS 4
+#define NDS32_VECTOR_MACHINE_ERROR 5
+#define NDS32_VECTOR_DEBUG_RELATED 6
+#define NDS32_VECTOR_GENERAL_EXCEPTION 7
+#define NDS32_VECTOR_SYSCALL 8
+#define NDS32_VECTOR_INTERRUPT_HW0 9
+#define NDS32_VECTOR_INTERRUPT_HW1 10
+#define NDS32_VECTOR_INTERRUPT_HW2 11
+#define NDS32_VECTOR_INTERRUPT_HW3 12
+#define NDS32_VECTOR_INTERRUPT_HW4 13
+#define NDS32_VECTOR_INTERRUPT_HW5 14
+#define NDS32_VECTOR_INTERRUPT_HW6 15
+#define NDS32_VECTOR_SWI 15 /* THIS IS FOR IVIC MODE ONLY */
+#define NDS32_VECTOR_INTERRUPT_HW7 16
+#define NDS32_VECTOR_INTERRUPT_HW8 17
+#define NDS32_VECTOR_INTERRUPT_HW9 18
+#define NDS32_VECTOR_INTERRUPT_HW10 19
+#define NDS32_VECTOR_INTERRUPT_HW11 20
+#define NDS32_VECTOR_INTERRUPT_HW12 21
+#define NDS32_VECTOR_INTERRUPT_HW13 22
+#define NDS32_VECTOR_INTERRUPT_HW14 23
+#define NDS32_VECTOR_INTERRUPT_HW15 24
+#define NDS32_VECTOR_INTERRUPT_HW16 25
+#define NDS32_VECTOR_INTERRUPT_HW17 26
+#define NDS32_VECTOR_INTERRUPT_HW18 27
+#define NDS32_VECTOR_INTERRUPT_HW19 28
+#define NDS32_VECTOR_INTERRUPT_HW20 29
+#define NDS32_VECTOR_INTERRUPT_HW21 30
+#define NDS32_VECTOR_INTERRUPT_HW22 31
+#define NDS32_VECTOR_INTERRUPT_HW23 32
+#define NDS32_VECTOR_INTERRUPT_HW24 33
+#define NDS32_VECTOR_INTERRUPT_HW25 34
+#define NDS32_VECTOR_INTERRUPT_HW26 35
+#define NDS32_VECTOR_INTERRUPT_HW27 36
+#define NDS32_VECTOR_INTERRUPT_HW28 37
+#define NDS32_VECTOR_INTERRUPT_HW29 38
+#define NDS32_VECTOR_INTERRUPT_HW30 39
+#define NDS32_VECTOR_INTERRUPT_HW31 40
+#define NDS32_VECTOR_INTERRUPT_HW32 41
+#define NDS32_VECTOR_INTERRUPT_HW33 42
+#define NDS32_VECTOR_INTERRUPT_HW34 43
+#define NDS32_VECTOR_INTERRUPT_HW35 44
+#define NDS32_VECTOR_INTERRUPT_HW36 45
+#define NDS32_VECTOR_INTERRUPT_HW37 46
+#define NDS32_VECTOR_INTERRUPT_HW38 47
+#define NDS32_VECTOR_INTERRUPT_HW39 48
+#define NDS32_VECTOR_INTERRUPT_HW40 49
+#define NDS32_VECTOR_INTERRUPT_HW41 50
+#define NDS32_VECTOR_INTERRUPT_HW42 51
+#define NDS32_VECTOR_INTERRUPT_HW43 52
+#define NDS32_VECTOR_INTERRUPT_HW44 53
+#define NDS32_VECTOR_INTERRUPT_HW45 54
+#define NDS32_VECTOR_INTERRUPT_HW46 55
+#define NDS32_VECTOR_INTERRUPT_HW47 56
+#define NDS32_VECTOR_INTERRUPT_HW48 57
+#define NDS32_VECTOR_INTERRUPT_HW49 58
+#define NDS32_VECTOR_INTERRUPT_HW50 59
+#define NDS32_VECTOR_INTERRUPT_HW51 60
+#define NDS32_VECTOR_INTERRUPT_HW52 61
+#define NDS32_VECTOR_INTERRUPT_HW53 62
+#define NDS32_VECTOR_INTERRUPT_HW54 63
+#define NDS32_VECTOR_INTERRUPT_HW55 64
+#define NDS32_VECTOR_INTERRUPT_HW56 65
+#define NDS32_VECTOR_INTERRUPT_HW57 66
+#define NDS32_VECTOR_INTERRUPT_HW58 67
+#define NDS32_VECTOR_INTERRUPT_HW59 68
+#define NDS32_VECTOR_INTERRUPT_HW60 69
+#define NDS32_VECTOR_INTERRUPT_HW61 70
+#define NDS32_VECTOR_INTERRUPT_HW62 71
+#define NDS32_VECTOR_INTERRUPT_HW63 72
+
+#define NDS32ATTR_RESET(option) __attribute__((reset(option)))
+#define NDS32ATTR_EXCEPT(type) __attribute__((exception(type)))
+#define NDS32ATTR_EXCEPTION(type) __attribute__((exception(type)))
+#define NDS32ATTR_INTERRUPT(type) __attribute__((interrupt(type)))
+#define NDS32ATTR_ISR(type) __attribute__((interrupt(type)))
+
+#endif /* nds32_isr.h */