]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/igen/gen-semantics.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / igen / gen-semantics.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3 Copyright 2002-2024 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22
23
24 #include "misc.h"
25 #include "lf.h"
26 #include "table.h"
27 #include "filter.h"
28 #include "igen.h"
29
30 #include "ld-insn.h"
31 #include "ld-decode.h"
32
33 #include "gen.h"
34
35 #include "gen-semantics.h"
36 #include "gen-icache.h"
37 #include "gen-idecode.h"
38
39
40 static void
41 print_semantic_function_header (lf *file,
42 const char *basename,
43 const char *format_name,
44 const opcode_bits *expanded_bits,
45 int is_function_definition,
46 int nr_prefetched_words)
47 {
48 int indent;
49 lf_printf (file, "\n");
50 lf_print__function_type_function (file, print_semantic_function_type,
51 "EXTERN_SEMANTICS",
52 (is_function_definition ? "\n" : " "));
53 indent = print_function_name (file,
54 basename,
55 format_name,
56 NULL,
57 expanded_bits,
58 function_name_prefix_semantics);
59 if (is_function_definition)
60 {
61 indent += lf_printf (file, " ");
62 lf_indent (file, +indent);
63 }
64 else
65 {
66 lf_printf (file, "\n");
67 }
68 lf_printf (file, "(");
69 lf_indent (file, +1);
70 print_semantic_function_formal (file, nr_prefetched_words);
71 lf_indent (file, -1);
72 lf_printf (file, ")");
73 if (is_function_definition)
74 {
75 lf_indent (file, -indent);
76 }
77 else
78 {
79 lf_printf (file, ";");
80 }
81 lf_printf (file, "\n");
82 }
83
84 void
85 print_semantic_declaration (lf *file,
86 const insn_entry *insn,
87 const opcode_bits *expanded_bits,
88 const insn_opcodes *opcodes,
89 int nr_prefetched_words)
90 {
91 print_semantic_function_header (file,
92 insn->name,
93 insn->format_name,
94 expanded_bits,
95 0 /* is not function definition */ ,
96 nr_prefetched_words);
97 }
98 \f
99
100
101 /* generate the semantics.c file */
102
103
104 void
105 print_idecode_invalid (lf *file, const char *result, invalid_type type)
106 {
107 const char *name;
108 switch (type)
109 {
110 default:
111 name = "unknown";
112 break;
113 case invalid_illegal:
114 name = "illegal";
115 break;
116 case invalid_fp_unavailable:
117 name = "fp_unavailable";
118 break;
119 case invalid_wrong_slot:
120 name = "wrong_slot";
121 break;
122 }
123 if (options.gen.code == generate_jumps)
124 {
125 lf_printf (file, "goto %s_%s;\n",
126 (options.gen.icache ? "icache" : "semantic"), name);
127 }
128 else if (options.gen.icache)
129 {
130 lf_printf (file, "%s %sicache_%s (", result,
131 options.module.global.prefix.l, name);
132 print_icache_function_actual (file, 0);
133 lf_printf (file, ");\n");
134 }
135 else
136 {
137 lf_printf (file, "%s %ssemantic_%s (", result,
138 options.module.global.prefix.l, name);
139 print_semantic_function_actual (file, 0);
140 lf_printf (file, ");\n");
141 }
142 }
143
144
145 void
146 print_semantic_body (lf *file,
147 const insn_entry *instruction,
148 const opcode_bits *expanded_bits,
149 const insn_opcodes *opcodes)
150 {
151 /* validate the instruction, if a cache this has already been done */
152 if (!options.gen.icache)
153 {
154 print_idecode_validate (file, instruction, opcodes);
155 }
156
157 print_itrace (file, instruction, 0 /*put_value_in_cache */ );
158
159 /* generate the instruction profile call - this is delayed until
160 after the instruction has been verified. The count macro
161 generated is prefixed by ITABLE_PREFIX */
162 {
163 lf_printf (file, "\n");
164 lf_indent_suppress (file);
165 lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n",
166 options.module.itable.prefix.u);
167 lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n",
168 options.module.itable.prefix.u);
169 lf_indent_suppress (file);
170 lf_printf (file, "#endif\n");
171 }
172
173 /* generate the model call - this is delayed until after the
174 instruction has been verified */
175 {
176 lf_printf (file, "\n");
177 lf_indent_suppress (file);
178 lf_printf (file, "#if defined (WITH_MON)\n");
179 lf_printf (file, "/* monitoring: */\n");
180 lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
181 lf_printf (file, " mon_issue (");
182 print_function_name (file,
183 instruction->name,
184 instruction->format_name,
185 NULL, NULL, function_name_prefix_itable);
186 lf_printf (file, ", cpu, cia);\n");
187 lf_indent_suppress (file);
188 lf_printf (file, "#endif\n");
189 lf_printf (file, "\n");
190 }
191
192 /* determine the new instruction address */
193 {
194 lf_printf (file, "/* keep the next instruction address handy */\n");
195 if (options.gen.nia == nia_is_invalid)
196 {
197 lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n",
198 options.module.global.prefix.u);
199 }
200 else
201 {
202 int nr_immeds = instruction->nr_words - 1;
203 if (options.gen.delayed_branch)
204 {
205 if (nr_immeds > 0)
206 {
207 lf_printf (file, "cia.dp += %d * %d; %s\n",
208 options.insn_bit_size / 8, nr_immeds,
209 "/* skip dp immeds */");
210 }
211 lf_printf (file, "nia.ip = cia.dp; %s\n",
212 "/* instruction pointer */");
213 lf_printf (file, "nia.dp = cia.dp + %d; %s\n",
214 options.insn_bit_size / 8,
215 "/* delayed-slot pointer */");
216 }
217 else
218 {
219 if (nr_immeds > 0)
220 {
221 lf_printf (file, "nia = cia + %d * (%d + 1); %s\n",
222 options.insn_bit_size / 8, nr_immeds,
223 "/* skip immeds as well */");
224
225 }
226 else
227 {
228 lf_printf (file, "nia = cia + %d;\n",
229 options.insn_bit_size / 8);
230 }
231 }
232 }
233 }
234
235 /* if conditional, generate code to verify that the instruction
236 should be issued */
237 if (filter_is_member (instruction->options, "c")
238 || options.gen.conditional_issue)
239 {
240 lf_printf (file, "\n");
241 lf_printf (file, "/* execute only if conditional passes */\n");
242 lf_printf (file, "if (IS_CONDITION_OK)\n");
243 lf_printf (file, " {\n");
244 lf_indent (file, +4);
245 /* FIXME - need to log a conditional failure */
246 }
247
248 /* Architecture expects a REG to be zero. Instead of having to
249 check every read to see if it is refering to that REG just zap it
250 at the start of every instruction */
251 if (options.gen.zero_reg)
252 {
253 lf_printf (file, "\n");
254 lf_printf (file, "/* Architecture expects REG to be zero */\n");
255 lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
256 }
257
258 /* generate the code (or at least something */
259 lf_printf (file, "\n");
260 lf_printf (file, "/* semantics: */\n");
261 if (instruction->code != NULL)
262 {
263 /* true code */
264 lf_printf (file, "{\n");
265 /* NB: Do not indent the code. If the .igen source files cause a compiler
266 warning, the diagnostics can read the line from the original source,
267 but use column offsets from the generated files, causing columns to be
268 misaligned. It makes the generated code slightly more difficult to
269 read, but accurate compiler diagnostics relative to the original source
270 are more important here.
271 lf_indent (file, +2); */
272 lf_print__line_ref (file, instruction->code->line);
273 table_print_code (file, instruction->code);
274 /* NB: Disabled -- see above.
275 lf_indent (file, -2); */
276 lf_printf (file, "}\n");
277 lf_print__internal_ref (file);
278 }
279 else if (filter_is_member (instruction->options, "nop"))
280 {
281 lf_print__internal_ref (file);
282 }
283 else
284 {
285 const char *prefix = "sim_engine_abort (";
286 int indent = strlen (prefix);
287 /* abort so it is implemented now */
288 lf_print__line_ref (file, instruction->line);
289 lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
290 lf_indent (file, +indent);
291 lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
292 filter_filename (instruction->line->file_name),
293 instruction->line->line_nr);
294 lf_printf (file, "(long) CIA, \\\n");
295 lf_printf (file, "%sitable[MY_INDEX].name);\n",
296 options.module.itable.prefix.l);
297 lf_indent (file, -indent);
298 lf_print__internal_ref (file);
299 }
300
301 /* Close off the conditional execution */
302 if (filter_is_member (instruction->options, "c")
303 || options.gen.conditional_issue)
304 {
305 lf_indent (file, -4);
306 lf_printf (file, " }\n");
307 }
308 }
309
310 static void
311 print_c_semantic (lf *file,
312 const insn_entry *instruction,
313 const opcode_bits *expanded_bits,
314 const insn_opcodes *opcodes,
315 cache_entry *cache_rules,
316 int nr_prefetched_words)
317 {
318
319 lf_printf (file, "{\n");
320 lf_indent (file, +2);
321
322 print_my_defines (file,
323 instruction->name,
324 instruction->format_name, expanded_bits);
325 lf_printf (file, "\n");
326 print_icache_body (file,
327 instruction,
328 expanded_bits,
329 cache_rules,
330 (options.gen.direct_access
331 ? define_variables
332 : declare_variables),
333 (options.gen.icache
334 ? get_values_from_icache
335 : do_not_use_icache), nr_prefetched_words);
336
337 lf_printf (file, "%sinstruction_address nia;\n",
338 options.module.global.prefix.l);
339 print_semantic_body (file, instruction, expanded_bits, opcodes);
340 lf_printf (file, "return nia;\n");
341
342 /* generate something to clean up any #defines created for the cache */
343 if (options.gen.direct_access)
344 {
345 print_icache_body (file,
346 instruction,
347 expanded_bits,
348 cache_rules,
349 undef_variables,
350 (options.gen.icache
351 ? get_values_from_icache
352 : do_not_use_icache), nr_prefetched_words);
353 }
354
355 lf_indent (file, -2);
356 lf_printf (file, "}\n");
357 }
358
359 static void
360 print_c_semantic_function (lf *file,
361 const insn_entry *instruction,
362 const opcode_bits *expanded_bits,
363 const insn_opcodes *opcodes,
364 cache_entry *cache_rules,
365 int nr_prefetched_words)
366 {
367 /* build the semantic routine to execute the instruction */
368 print_semantic_function_header (file,
369 instruction->name,
370 instruction->format_name,
371 expanded_bits,
372 1 /*is-function-definition */ ,
373 nr_prefetched_words);
374 print_c_semantic (file,
375 instruction,
376 expanded_bits, opcodes, cache_rules, nr_prefetched_words);
377 }
378
379 void
380 print_semantic_definition (lf *file,
381 const insn_entry *insn,
382 const opcode_bits *expanded_bits,
383 const insn_opcodes *opcodes,
384 cache_entry *cache_rules,
385 int nr_prefetched_words)
386 {
387 print_c_semantic_function (file,
388 insn,
389 expanded_bits,
390 opcodes, cache_rules, nr_prefetched_words);
391 }