diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-21 22:01:24 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-21 22:01:24 +0000 |
commit | ffde65b31066f17eef243be882bb89a6e19370aa (patch) | |
tree | ea876d041c0a63eefccdac5416a8678e75da4cfc /gcc/config/nds32/nds32-isr.c | |
parent | a8c7acc4db08ce7c8ac3ddcb943f9219e2893792 (diff) | |
download | gcc-ffde65b31066f17eef243be882bb89a6e19370aa.tar.gz |
[.]
2015-01-21 Basile Starynkevitch <basile@starynkevitch.net>
{{merged with trunk -i.e. GCC5.0 in stage4- using
svn merge -r209216:219879 svn+ssh://bstarynk@gcc.gnu.org/svn/gcc/trunk
but should probably have used
svn merge -r209216:219879 ^/trunk
we don't use svnmerge.py anymore since our svn is version 1.8.10
}}
VERY UNSTABLE
2015-01-20 Basile Starynkevitch <basile@starynkevitch.net>
Move previous topdir ChangeLog.MELT to ChangeLog.MELT.2008-2014
[contrib/]
2015-01-21 Basile Starynkevitch <basile@starynkevitch.net>
* MELT-Plugin-Makefile: Able to make upgrade-melt as a
plugin. Works for GCC 5.0. Remove GCC 4.7 old stuff.
Move previous contrib/ChangeLog.MELT to ChangeLog.MELT.2008-2014
[gcc/]
2015-01-21 Basile Starynkevitch <basile@starynkevitch.net>
{{merged with trunk -i.e. GCC5.0 in stage4- using
svn merge -r209216:219879 svn+ssh://bstarynk@gcc.gnu.org/svn/gcc/trunk
but should probably have used
svn merge -r209216:219879 ^/trunk
**@@@ UNSTABLE since libmelt-ana-gimple.melt not compiling, but
translator painfully bootstrapping!!@@@@ }}
* toplev.c: Merged manually by keeping MELT extra stuff.
* toplev.h: Likewise.
* gengtype.c: Add "melt-runtime.h" in list, but merged with trunk.
* melt-runtime.h (MELT_VERSION_STRING): Bump to "1.2-pre-merged".
(meltgc_walk_gimple_seq): Remove.
(gt_ggc_mx_gimple_statement_d): Same for GCC 4.9 & 5.0
* melt-runtime.cc: Update copyright year.
(ggc_alloc_cleared_melt_valuevector_st, melt_resize_scangcvect):
Call ggc_internal_cleared_alloc.
(melt_val2passflag): Skip TODO_verify_ssa, TODO_verify_flow,
TODO_verify_stmts, TODO_verify_rtl_sharing for GCC 5.0.
(meltgc_walkstmt_cb, meltgc_walktree_cb)
(melt_tree_walk_frame_size, meltgc_walk_gimple_seq): Remove.
(melt_gt_ggc_mx_gimple_seq_d): Call
gt_ggc_mx_gimple_statement_base.
* melt-build-script.tpl: Update copyright year. Don't symlink
meltrunsup.h anymore.
* melt-build-script.sh: Regenerate.
* melt/warmelt-base.melt: Update copyright year.
(valdesc_object, valdesc_mapobjects, valdesc_mapstrings)
(valdesc_multiple, valdesc_closure, valdesc_routine, valdesc_hook)
(valdesc_bucketlongs, valdesc_jsonobject, valdesc_string)
(valdesc_strbuf, valdesc_pair, valdesc_list, valdesc_int)
(valdesc_double, valdesc_mixint, valdesc_mixloc)
(valdesc_mixbigint, valdesc_real, valdesc_special_data): Use
ggc_internal_alloc & ggc_internal_cleared_alloc for GCC 5.0.
(json_canonical_name): Use ISUPPER, ISALPHA, TOUPPER instead of
their standard <ctype.h> lowercase macros.
* melt/warmelt-modes.melt: Update copyright year.
(generate_runtypesupport_forwcopy_fun): Emit both GCC 4.9 & 5.0
compatible code.
* melt/libmelt-ana-base.melt: Update copyright year.
* melt/libmelt-ana-gimple.melt: TO BE IMPROVED
* melt/generated/*: Painfully regenerated several times thru GCC
4.9 MELT plugin.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@219975 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nds32/nds32-isr.c')
-rw-r--r-- | gcc/config/nds32/nds32-isr.c | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c new file mode 100644 index 00000000000..1896fde9f1e --- /dev/null +++ b/gcc/config/nds32/nds32-isr.c @@ -0,0 +1,629 @@ +/* Subroutines used for ISR of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2015 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. + + 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 "hash-set.h" +#include "machmode.h" +#include "vec.h" +#include "double-int.h" +#include "input.h" +#include "alias.h" +#include "symtab.h" +#include "wide-int.h" +#include "inchash.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 "hashtab.h" +#include "statistics.h" +#include "real.h" +#include "fixed-value.h" +#include "insn-config.h" +#include "expmed.h" +#include "dojump.h" +#include "explow.h" +#include "emit-rtl.h" +#include "stmt.h" +#include "expr.h" +#include "recog.h" +#include "diagnostic-core.h" +#include "dominance.h" +#include "cfg.h" +#include "cfgrtl.h" +#include "cfganal.h" +#include "lcm.h" +#include "cfgbuild.h" +#include "cfgcleanup.h" +#include "predict.h" +#include "basic-block.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"); + } + } +} + +/* Return true if FUNC is a isr function. */ +bool +nds32_isr_function_p (tree func) +{ + tree t_intr; + tree t_excp; + tree t_reset; + + 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_reset = lookup_attribute ("reset", attrs); + + return ((t_intr != NULL_TREE) + || (t_excp != NULL_TREE) + || (t_reset != NULL_TREE)); +} + +/* ------------------------------------------------------------------------ */ |