annotate gcc/config/nds32/nds32-isr.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Subroutines used for ISR of Andes NDS32 cpu for GNU compiler
kono
parents:
diff changeset
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Andes Technology Corporation.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
8 under the terms of the GNU General Public License as published
kono
parents:
diff changeset
9 by the Free Software Foundation; either version 3, or (at your
kono
parents:
diff changeset
10 option) any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT
kono
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
kono
parents:
diff changeset
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
kono
parents:
diff changeset
15 License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 /* ------------------------------------------------------------------------ */
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 #include "config.h"
kono
parents:
diff changeset
24 #include "system.h"
kono
parents:
diff changeset
25 #include "coretypes.h"
kono
parents:
diff changeset
26 #include "backend.h"
kono
parents:
diff changeset
27 #include "target.h"
kono
parents:
diff changeset
28 #include "rtl.h"
kono
parents:
diff changeset
29 #include "tree.h"
kono
parents:
diff changeset
30 #include "stringpool.h"
kono
parents:
diff changeset
31 #include "attribs.h"
kono
parents:
diff changeset
32 #include "diagnostic-core.h"
kono
parents:
diff changeset
33 #include "output.h"
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 /* ------------------------------------------------------------------------ */
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 /* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
kono
parents:
diff changeset
38 0 for reset handler with __attribute__((reset())),
kono
parents:
diff changeset
39 1-8 for exception handler with __attribute__((exception(1,...,8))),
kono
parents:
diff changeset
40 and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
kono
parents:
diff changeset
41 We use an array to record essential information for each vector. */
kono
parents:
diff changeset
42 static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 /* ------------------------------------------------------------------------ */
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 /* A helper function to emit section head template. */
kono
parents:
diff changeset
47 static void
kono
parents:
diff changeset
48 nds32_emit_section_head_template (char section_name[],
kono
parents:
diff changeset
49 char symbol_name[],
kono
parents:
diff changeset
50 int align_value,
kono
parents:
diff changeset
51 bool object_p)
kono
parents:
diff changeset
52 {
kono
parents:
diff changeset
53 const char *flags_str;
kono
parents:
diff changeset
54 const char *type_str;
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 flags_str = (object_p) ? "\"a\"" : "\"ax\"";
kono
parents:
diff changeset
57 type_str = (object_p) ? "@object" : "@function";
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str);
kono
parents:
diff changeset
60 fprintf (asm_out_file, "\t.align\t%d\n", align_value);
kono
parents:
diff changeset
61 fprintf (asm_out_file, "\t.global\t%s\n", symbol_name);
kono
parents:
diff changeset
62 fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str);
kono
parents:
diff changeset
63 fprintf (asm_out_file, "%s:\n", symbol_name);
kono
parents:
diff changeset
64 }
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 /* A helper function to emit section tail template. */
kono
parents:
diff changeset
67 static void
kono
parents:
diff changeset
68 nds32_emit_section_tail_template (char symbol_name[])
kono
parents:
diff changeset
69 {
kono
parents:
diff changeset
70 fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name);
kono
parents:
diff changeset
71 }
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 /* Function to emit isr jump table section. */
kono
parents:
diff changeset
74 static void
kono
parents:
diff changeset
75 nds32_emit_isr_jmptbl_section (int vector_id)
kono
parents:
diff changeset
76 {
kono
parents:
diff changeset
77 char section_name[100];
kono
parents:
diff changeset
78 char symbol_name[100];
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 /* Prepare jmptbl section and symbol name. */
kono
parents:
diff changeset
81 snprintf (section_name, sizeof (section_name),
kono
parents:
diff changeset
82 ".nds32_jmptbl.%02d", vector_id);
kono
parents:
diff changeset
83 snprintf (symbol_name, sizeof (symbol_name),
kono
parents:
diff changeset
84 "_nds32_jmptbl_%02d", vector_id);
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
kono
parents:
diff changeset
87 fprintf (asm_out_file, "\t.word\t%s\n",
kono
parents:
diff changeset
88 nds32_isr_vectors[vector_id].func_name);
kono
parents:
diff changeset
89 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
90 }
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 /* Function to emit isr vector section. */
kono
parents:
diff changeset
93 static void
kono
parents:
diff changeset
94 nds32_emit_isr_vector_section (int vector_id)
kono
parents:
diff changeset
95 {
kono
parents:
diff changeset
96 unsigned int vector_number_offset = 0;
kono
parents:
diff changeset
97 const char *c_str = "CATEGORY";
kono
parents:
diff changeset
98 const char *sr_str = "SR";
kono
parents:
diff changeset
99 const char *nt_str = "NT";
kono
parents:
diff changeset
100 const char *vs_str = "VS";
kono
parents:
diff changeset
101 char first_level_handler_name[100];
kono
parents:
diff changeset
102 char section_name[100];
kono
parents:
diff changeset
103 char symbol_name[100];
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 /* Set the vector number offset so that we can calculate
kono
parents:
diff changeset
106 the value that user specifies in the attribute.
kono
parents:
diff changeset
107 We also prepare the category string for first level handler name. */
kono
parents:
diff changeset
108 switch (nds32_isr_vectors[vector_id].category)
kono
parents:
diff changeset
109 {
kono
parents:
diff changeset
110 case NDS32_ISR_INTERRUPT:
kono
parents:
diff changeset
111 vector_number_offset = 9;
kono
parents:
diff changeset
112 c_str = "i";
kono
parents:
diff changeset
113 break;
kono
parents:
diff changeset
114 case NDS32_ISR_EXCEPTION:
kono
parents:
diff changeset
115 vector_number_offset = 0;
kono
parents:
diff changeset
116 c_str = "e";
kono
parents:
diff changeset
117 break;
kono
parents:
diff changeset
118 case NDS32_ISR_NONE:
kono
parents:
diff changeset
119 case NDS32_ISR_RESET:
kono
parents:
diff changeset
120 /* Normally it should not be here. */
kono
parents:
diff changeset
121 gcc_unreachable ();
kono
parents:
diff changeset
122 break;
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 /* Prepare save reg string for first level handler name. */
kono
parents:
diff changeset
126 switch (nds32_isr_vectors[vector_id].save_reg)
kono
parents:
diff changeset
127 {
kono
parents:
diff changeset
128 case NDS32_SAVE_ALL:
kono
parents:
diff changeset
129 sr_str = "sa";
kono
parents:
diff changeset
130 break;
kono
parents:
diff changeset
131 case NDS32_PARTIAL_SAVE:
kono
parents:
diff changeset
132 sr_str = "ps";
kono
parents:
diff changeset
133 break;
kono
parents:
diff changeset
134 }
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 /* Prepare nested type string for first level handler name. */
kono
parents:
diff changeset
137 switch (nds32_isr_vectors[vector_id].nested_type)
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 case NDS32_NESTED:
kono
parents:
diff changeset
140 nt_str = "ns";
kono
parents:
diff changeset
141 break;
kono
parents:
diff changeset
142 case NDS32_NOT_NESTED:
kono
parents:
diff changeset
143 nt_str = "nn";
kono
parents:
diff changeset
144 break;
kono
parents:
diff changeset
145 case NDS32_NESTED_READY:
kono
parents:
diff changeset
146 nt_str = "nr";
kono
parents:
diff changeset
147 break;
kono
parents:
diff changeset
148 }
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 /* Currently we have 4-byte or 16-byte size for each vector.
kono
parents:
diff changeset
151 If it is 4-byte, the first level handler name has suffix string "_4b". */
kono
parents:
diff changeset
152 vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 /* Now we can create first level handler name. */
kono
parents:
diff changeset
155 snprintf (first_level_handler_name, sizeof (first_level_handler_name),
kono
parents:
diff changeset
156 "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 /* Prepare vector section and symbol name. */
kono
parents:
diff changeset
159 snprintf (section_name, sizeof (section_name),
kono
parents:
diff changeset
160 ".nds32_vector.%02d", vector_id);
kono
parents:
diff changeset
161 snprintf (symbol_name, sizeof (symbol_name),
kono
parents:
diff changeset
162 "_nds32_vector_%02d%s", vector_id, vs_str);
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 /* Everything is ready. We can start emit vector section content. */
kono
parents:
diff changeset
166 nds32_emit_section_head_template (section_name, symbol_name,
kono
parents:
diff changeset
167 floor_log2 (nds32_isr_vector_size), false);
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 /* According to the vector size, the instructions in the
kono
parents:
diff changeset
170 vector section may be different. */
kono
parents:
diff changeset
171 if (nds32_isr_vector_size == 4)
kono
parents:
diff changeset
172 {
kono
parents:
diff changeset
173 /* This block is for 4-byte vector size.
kono
parents:
diff changeset
174 Hardware $VID support is necessary and only one instruction
kono
parents:
diff changeset
175 is needed in vector section. */
kono
parents:
diff changeset
176 fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
kono
parents:
diff changeset
177 first_level_handler_name);
kono
parents:
diff changeset
178 }
kono
parents:
diff changeset
179 else
kono
parents:
diff changeset
180 {
kono
parents:
diff changeset
181 /* This block is for 16-byte vector size.
kono
parents:
diff changeset
182 There is NO hardware $VID so that we need several instructions
kono
parents:
diff changeset
183 such as pushing GPRs and preparing software vid at vector section.
kono
parents:
diff changeset
184 For pushing GPRs, there are four variations for
kono
parents:
diff changeset
185 16-byte vector content and we have to handle each combination.
kono
parents:
diff changeset
186 For preparing software vid, note that the vid need to
kono
parents:
diff changeset
187 be substracted vector_number_offset. */
kono
parents:
diff changeset
188 if (TARGET_REDUCED_REGS)
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
kono
parents:
diff changeset
191 {
kono
parents:
diff changeset
192 /* Case of reduced set registers and save_all attribute. */
kono
parents:
diff changeset
193 fprintf (asm_out_file, "\t! reduced set regs + save_all\n");
kono
parents:
diff changeset
194 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
kono
parents:
diff changeset
195 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198 else
kono
parents:
diff changeset
199 {
kono
parents:
diff changeset
200 /* Case of reduced set registers and partial_save attribute. */
kono
parents:
diff changeset
201 fprintf (asm_out_file, "\t! reduced set regs + partial_save\n");
kono
parents:
diff changeset
202 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
kono
parents:
diff changeset
203 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
kono
parents:
diff changeset
204 }
kono
parents:
diff changeset
205 }
kono
parents:
diff changeset
206 else
kono
parents:
diff changeset
207 {
kono
parents:
diff changeset
208 if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 /* Case of full set registers and save_all attribute. */
kono
parents:
diff changeset
211 fprintf (asm_out_file, "\t! full set regs + save_all\n");
kono
parents:
diff changeset
212 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
kono
parents:
diff changeset
213 }
kono
parents:
diff changeset
214 else
kono
parents:
diff changeset
215 {
kono
parents:
diff changeset
216 /* Case of full set registers and partial_save attribute. */
kono
parents:
diff changeset
217 fprintf (asm_out_file, "\t! full set regs + partial_save\n");
kono
parents:
diff changeset
218 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
kono
parents:
diff changeset
219 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n",
kono
parents:
diff changeset
224 vector_id - vector_number_offset);
kono
parents:
diff changeset
225 fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
kono
parents:
diff changeset
226 first_level_handler_name);
kono
parents:
diff changeset
227 }
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
230 }
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* Function to emit isr reset handler content.
kono
parents:
diff changeset
233 Including all jmptbl/vector references, jmptbl section,
kono
parents:
diff changeset
234 vector section, nmi handler section, and warm handler section. */
kono
parents:
diff changeset
235 static void
kono
parents:
diff changeset
236 nds32_emit_isr_reset_content (void)
kono
parents:
diff changeset
237 {
kono
parents:
diff changeset
238 unsigned int i;
kono
parents:
diff changeset
239 unsigned int total_n_vectors;
kono
parents:
diff changeset
240 const char *vs_str;
kono
parents:
diff changeset
241 char reset_handler_name[100];
kono
parents:
diff changeset
242 char section_name[100];
kono
parents:
diff changeset
243 char symbol_name[100];
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
kono
parents:
diff changeset
246 vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 /* Create references in .rodata according to total number of vectors. */
kono
parents:
diff changeset
251 fprintf (asm_out_file, "\t.section\t.rodata\n");
kono
parents:
diff changeset
252 fprintf (asm_out_file, "\t.align\t2\n");
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 /* Emit jmptbl references. */
kono
parents:
diff changeset
255 fprintf (asm_out_file, "\t ! references to jmptbl section entries\n");
kono
parents:
diff changeset
256 for (i = 0; i < total_n_vectors; i++)
kono
parents:
diff changeset
257 fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i);
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 /* Emit vector references. */
kono
parents:
diff changeset
260 fprintf (asm_out_file, "\t ! references to vector section entries\n");
kono
parents:
diff changeset
261 for (i = 0; i < total_n_vectors; i++)
kono
parents:
diff changeset
262 fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 /* Emit jmptbl_00 section. */
kono
parents:
diff changeset
265 snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
kono
parents:
diff changeset
266 snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00");
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 fprintf (asm_out_file, "\t! ....................................\n");
kono
parents:
diff changeset
269 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
kono
parents:
diff changeset
270 fprintf (asm_out_file, "\t.word\t%s\n",
kono
parents:
diff changeset
271 nds32_isr_vectors[0].func_name);
kono
parents:
diff changeset
272 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 /* Emit vector_00 section. */
kono
parents:
diff changeset
275 snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
kono
parents:
diff changeset
276 snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
kono
parents:
diff changeset
277 snprintf (reset_handler_name, sizeof (reset_handler_name),
kono
parents:
diff changeset
278 "_nds32_reset%s", vs_str);
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 fprintf (asm_out_file, "\t! ....................................\n");
kono
parents:
diff changeset
281 nds32_emit_section_head_template (section_name, symbol_name,
kono
parents:
diff changeset
282 floor_log2 (nds32_isr_vector_size), false);
kono
parents:
diff changeset
283 fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n",
kono
parents:
diff changeset
284 reset_handler_name);
kono
parents:
diff changeset
285 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 /* Emit nmi handler section. */
kono
parents:
diff changeset
288 snprintf (section_name, sizeof (section_name), ".nds32_nmih");
kono
parents:
diff changeset
289 snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih");
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 fprintf (asm_out_file, "\t! ....................................\n");
kono
parents:
diff changeset
292 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
kono
parents:
diff changeset
293 fprintf (asm_out_file, "\t.word\t%s\n",
kono
parents:
diff changeset
294 (strlen (nds32_isr_vectors[0].nmi_name) == 0)
kono
parents:
diff changeset
295 ? "0"
kono
parents:
diff changeset
296 : nds32_isr_vectors[0].nmi_name);
kono
parents:
diff changeset
297 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 /* Emit warm handler section. */
kono
parents:
diff changeset
300 snprintf (section_name, sizeof (section_name), ".nds32_wrh");
kono
parents:
diff changeset
301 snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh");
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 fprintf (asm_out_file, "\t! ....................................\n");
kono
parents:
diff changeset
304 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
kono
parents:
diff changeset
305 fprintf (asm_out_file, "\t.word\t%s\n",
kono
parents:
diff changeset
306 (strlen (nds32_isr_vectors[0].warm_name) == 0)
kono
parents:
diff changeset
307 ? "0"
kono
parents:
diff changeset
308 : nds32_isr_vectors[0].warm_name);
kono
parents:
diff changeset
309 nds32_emit_section_tail_template (symbol_name);
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n");
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 /* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
kono
parents:
diff changeset
315 to check if there are any conflict isr-specific attributes being set.
kono
parents:
diff changeset
316 We need to check:
kono
parents:
diff changeset
317 1. Only 'save_all' or 'partial_save' in the attributes.
kono
parents:
diff changeset
318 2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
kono
parents:
diff changeset
319 3. Only 'interrupt', 'exception', or 'reset' in the attributes. */
kono
parents:
diff changeset
320 void
kono
parents:
diff changeset
321 nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
kono
parents:
diff changeset
322 {
kono
parents:
diff changeset
323 int save_all_p, partial_save_p;
kono
parents:
diff changeset
324 int nested_p, not_nested_p, nested_ready_p;
kono
parents:
diff changeset
325 int intr_p, excp_p, reset_p;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 /* Initialize variables. */
kono
parents:
diff changeset
328 save_all_p = partial_save_p = 0;
kono
parents:
diff changeset
329 nested_p = not_nested_p = nested_ready_p = 0;
kono
parents:
diff changeset
330 intr_p = excp_p = reset_p = 0;
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 /* We must check at MOST one attribute to set save-reg. */
kono
parents:
diff changeset
333 if (lookup_attribute ("save_all", func_attrs))
kono
parents:
diff changeset
334 save_all_p = 1;
kono
parents:
diff changeset
335 if (lookup_attribute ("partial_save", func_attrs))
kono
parents:
diff changeset
336 partial_save_p = 1;
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 if ((save_all_p + partial_save_p) > 1)
kono
parents:
diff changeset
339 error ("multiple save reg attributes to function %qD", func_decl);
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 /* We must check at MOST one attribute to set nested-type. */
kono
parents:
diff changeset
342 if (lookup_attribute ("nested", func_attrs))
kono
parents:
diff changeset
343 nested_p = 1;
kono
parents:
diff changeset
344 if (lookup_attribute ("not_nested", func_attrs))
kono
parents:
diff changeset
345 not_nested_p = 1;
kono
parents:
diff changeset
346 if (lookup_attribute ("nested_ready", func_attrs))
kono
parents:
diff changeset
347 nested_ready_p = 1;
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 if ((nested_p + not_nested_p + nested_ready_p) > 1)
kono
parents:
diff changeset
350 error ("multiple nested types attributes to function %qD", func_decl);
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 /* We must check at MOST one attribute to
kono
parents:
diff changeset
353 set interrupt/exception/reset. */
kono
parents:
diff changeset
354 if (lookup_attribute ("interrupt", func_attrs))
kono
parents:
diff changeset
355 intr_p = 1;
kono
parents:
diff changeset
356 if (lookup_attribute ("exception", func_attrs))
kono
parents:
diff changeset
357 excp_p = 1;
kono
parents:
diff changeset
358 if (lookup_attribute ("reset", func_attrs))
kono
parents:
diff changeset
359 reset_p = 1;
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 if ((intr_p + excp_p + reset_p) > 1)
kono
parents:
diff changeset
362 error ("multiple interrupt attributes to function %qD", func_decl);
kono
parents:
diff changeset
363 }
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365 /* Function to construct isr vectors information array.
kono
parents:
diff changeset
366 We DO NOT HAVE TO check if the attributes are valid
kono
parents:
diff changeset
367 because those works are supposed to be done on
kono
parents:
diff changeset
368 nds32_merge_decl_attributes() and nds32_insert_attributes(). */
kono
parents:
diff changeset
369 void
kono
parents:
diff changeset
370 nds32_construct_isr_vectors_information (tree func_attrs,
kono
parents:
diff changeset
371 const char *func_name)
kono
parents:
diff changeset
372 {
kono
parents:
diff changeset
373 tree save_all, partial_save;
kono
parents:
diff changeset
374 tree nested, not_nested, nested_ready;
kono
parents:
diff changeset
375 tree intr, excp, reset;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 save_all = lookup_attribute ("save_all", func_attrs);
kono
parents:
diff changeset
378 partial_save = lookup_attribute ("partial_save", func_attrs);
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 nested = lookup_attribute ("nested", func_attrs);
kono
parents:
diff changeset
381 not_nested = lookup_attribute ("not_nested", func_attrs);
kono
parents:
diff changeset
382 nested_ready = lookup_attribute ("nested_ready", func_attrs);
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384 intr = lookup_attribute ("interrupt", func_attrs);
kono
parents:
diff changeset
385 excp = lookup_attribute ("exception", func_attrs);
kono
parents:
diff changeset
386 reset = lookup_attribute ("reset", func_attrs);
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 /* If there is no interrupt/exception/reset, we can return immediately. */
kono
parents:
diff changeset
389 if (!intr && !excp && !reset)
kono
parents:
diff changeset
390 return;
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 /* If we are here, either we have interrupt/exception,
kono
parents:
diff changeset
393 or reset attribute. */
kono
parents:
diff changeset
394 if (intr || excp)
kono
parents:
diff changeset
395 {
kono
parents:
diff changeset
396 tree id_list;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 /* Prepare id list so that we can traverse and set vector id. */
kono
parents:
diff changeset
399 id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 while (id_list)
kono
parents:
diff changeset
402 {
kono
parents:
diff changeset
403 tree id;
kono
parents:
diff changeset
404 int vector_id;
kono
parents:
diff changeset
405 unsigned int vector_number_offset;
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 /* The way to handle interrupt or exception is the same,
kono
parents:
diff changeset
408 we just need to take care of actual vector number.
kono
parents:
diff changeset
409 For interrupt(0..63), the actual vector number is (9..72).
kono
parents:
diff changeset
410 For exception(1..8), the actual vector number is (1..8). */
kono
parents:
diff changeset
411 vector_number_offset = (intr) ? (9) : (0);
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 /* Pick up each vector id value. */
kono
parents:
diff changeset
414 id = TREE_VALUE (id_list);
kono
parents:
diff changeset
415 /* Add vector_number_offset to get actual vector number. */
kono
parents:
diff changeset
416 vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 /* Enable corresponding vector and set function name. */
kono
parents:
diff changeset
419 nds32_isr_vectors[vector_id].category = (intr)
kono
parents:
diff changeset
420 ? (NDS32_ISR_INTERRUPT)
kono
parents:
diff changeset
421 : (NDS32_ISR_EXCEPTION);
kono
parents:
diff changeset
422 strcpy (nds32_isr_vectors[vector_id].func_name, func_name);
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 /* Set register saving scheme. */
kono
parents:
diff changeset
425 if (save_all)
kono
parents:
diff changeset
426 nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL;
kono
parents:
diff changeset
427 else if (partial_save)
kono
parents:
diff changeset
428 nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE;
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 /* Set nested type. */
kono
parents:
diff changeset
431 if (nested)
kono
parents:
diff changeset
432 nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED;
kono
parents:
diff changeset
433 else if (not_nested)
kono
parents:
diff changeset
434 nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
kono
parents:
diff changeset
435 else if (nested_ready)
kono
parents:
diff changeset
436 nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
kono
parents:
diff changeset
437
kono
parents:
diff changeset
438 /* Advance to next id. */
kono
parents:
diff changeset
439 id_list = TREE_CHAIN (id_list);
kono
parents:
diff changeset
440 }
kono
parents:
diff changeset
441 }
kono
parents:
diff changeset
442 else
kono
parents:
diff changeset
443 {
kono
parents:
diff changeset
444 tree id_list;
kono
parents:
diff changeset
445 tree id;
kono
parents:
diff changeset
446 tree nmi, warm;
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 /* Deal with reset attribute. Its vector number is always 0. */
kono
parents:
diff changeset
449 nds32_isr_vectors[0].category = NDS32_ISR_RESET;
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 /* Prepare id_list and identify id value so that
kono
parents:
diff changeset
452 we can set total number of vectors. */
kono
parents:
diff changeset
453 id_list = TREE_VALUE (reset);
kono
parents:
diff changeset
454 id = TREE_VALUE (id_list);
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 /* The total vectors = interrupt + exception numbers + reset.
kono
parents:
diff changeset
457 There are 8 exception and 1 reset in nds32 architecture. */
kono
parents:
diff changeset
458 nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1;
kono
parents:
diff changeset
459 strcpy (nds32_isr_vectors[0].func_name, func_name);
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 /* Retrieve nmi and warm function. */
kono
parents:
diff changeset
462 nmi = lookup_attribute ("nmi", func_attrs);
kono
parents:
diff changeset
463 warm = lookup_attribute ("warm", func_attrs);
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 if (nmi != NULL_TREE)
kono
parents:
diff changeset
466 {
kono
parents:
diff changeset
467 tree nmi_func_list;
kono
parents:
diff changeset
468 tree nmi_func;
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 nmi_func_list = TREE_VALUE (nmi);
kono
parents:
diff changeset
471 nmi_func = TREE_VALUE (nmi_func_list);
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 /* Record nmi function name. */
kono
parents:
diff changeset
474 strcpy (nds32_isr_vectors[0].nmi_name,
kono
parents:
diff changeset
475 IDENTIFIER_POINTER (nmi_func));
kono
parents:
diff changeset
476 }
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 if (warm != NULL_TREE)
kono
parents:
diff changeset
479 {
kono
parents:
diff changeset
480 tree warm_func_list;
kono
parents:
diff changeset
481 tree warm_func;
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 warm_func_list = TREE_VALUE (warm);
kono
parents:
diff changeset
484 warm_func = TREE_VALUE (warm_func_list);
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* Record warm function name. */
kono
parents:
diff changeset
487 strcpy (nds32_isr_vectors[0].warm_name,
kono
parents:
diff changeset
488 IDENTIFIER_POINTER (warm_func));
kono
parents:
diff changeset
489 }
kono
parents:
diff changeset
490 }
kono
parents:
diff changeset
491 }
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 /* A helper function to handle isr stuff at the beginning of asm file. */
kono
parents:
diff changeset
494 void
kono
parents:
diff changeset
495 nds32_asm_file_start_for_isr (void)
kono
parents:
diff changeset
496 {
kono
parents:
diff changeset
497 int i;
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499 /* Initialize isr vector information array before compiling functions. */
kono
parents:
diff changeset
500 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
kono
parents:
diff changeset
501 {
kono
parents:
diff changeset
502 nds32_isr_vectors[i].category = NDS32_ISR_NONE;
kono
parents:
diff changeset
503 strcpy (nds32_isr_vectors[i].func_name, "");
kono
parents:
diff changeset
504 nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
kono
parents:
diff changeset
505 nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
kono
parents:
diff changeset
506 nds32_isr_vectors[i].total_n_vectors = 0;
kono
parents:
diff changeset
507 strcpy (nds32_isr_vectors[i].nmi_name, "");
kono
parents:
diff changeset
508 strcpy (nds32_isr_vectors[i].warm_name, "");
kono
parents:
diff changeset
509 }
kono
parents:
diff changeset
510 }
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 /* A helper function to handle isr stuff at the end of asm file. */
kono
parents:
diff changeset
513 void
kono
parents:
diff changeset
514 nds32_asm_file_end_for_isr (void)
kono
parents:
diff changeset
515 {
kono
parents:
diff changeset
516 int i;
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
kono
parents:
diff changeset
519 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
kono
parents:
diff changeset
520 if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
kono
parents:
diff changeset
521 break;
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 if (i == NDS32_N_ISR_VECTORS)
kono
parents:
diff changeset
524 return;
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 /* At least one vector is NOT NDS32_ISR_NONE,
kono
parents:
diff changeset
527 we should output isr vector information. */
kono
parents:
diff changeset
528 fprintf (asm_out_file, "\t! ------------------------------------\n");
kono
parents:
diff changeset
529 fprintf (asm_out_file, "\t! The isr vector information:\n");
kono
parents:
diff changeset
530 fprintf (asm_out_file, "\t! ------------------------------------\n");
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 /* Check reset handler first. Its vector number is always 0. */
kono
parents:
diff changeset
533 if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
kono
parents:
diff changeset
534 {
kono
parents:
diff changeset
535 nds32_emit_isr_reset_content ();
kono
parents:
diff changeset
536 fprintf (asm_out_file, "\t! ------------------------------------\n");
kono
parents:
diff changeset
537 }
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 /* Check other vectors, starting from vector number 1. */
kono
parents:
diff changeset
540 for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
kono
parents:
diff changeset
541 {
kono
parents:
diff changeset
542 if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
kono
parents:
diff changeset
543 || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
kono
parents:
diff changeset
544 {
kono
parents:
diff changeset
545 /* Found one vector which is interupt or exception.
kono
parents:
diff changeset
546 Output its jmptbl and vector section content. */
kono
parents:
diff changeset
547 fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
kono
parents:
diff changeset
548 fprintf (asm_out_file, "\t! ------------------------------------\n");
kono
parents:
diff changeset
549 nds32_emit_isr_jmptbl_section (i);
kono
parents:
diff changeset
550 fprintf (asm_out_file, "\t! ....................................\n");
kono
parents:
diff changeset
551 nds32_emit_isr_vector_section (i);
kono
parents:
diff changeset
552 fprintf (asm_out_file, "\t! ------------------------------------\n");
kono
parents:
diff changeset
553 }
kono
parents:
diff changeset
554 }
kono
parents:
diff changeset
555 }
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 /* Return true if FUNC is a isr function. */
kono
parents:
diff changeset
558 bool
kono
parents:
diff changeset
559 nds32_isr_function_p (tree func)
kono
parents:
diff changeset
560 {
kono
parents:
diff changeset
561 tree t_intr;
kono
parents:
diff changeset
562 tree t_excp;
kono
parents:
diff changeset
563 tree t_reset;
kono
parents:
diff changeset
564
kono
parents:
diff changeset
565 tree attrs;
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 if (TREE_CODE (func) != FUNCTION_DECL)
kono
parents:
diff changeset
568 abort ();
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 attrs = DECL_ATTRIBUTES (func);
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 t_intr = lookup_attribute ("interrupt", attrs);
kono
parents:
diff changeset
573 t_excp = lookup_attribute ("exception", attrs);
kono
parents:
diff changeset
574 t_reset = lookup_attribute ("reset", attrs);
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 return ((t_intr != NULL_TREE)
kono
parents:
diff changeset
577 || (t_excp != NULL_TREE)
kono
parents:
diff changeset
578 || (t_reset != NULL_TREE));
kono
parents:
diff changeset
579 }
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 /* ------------------------------------------------------------------------ */