]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/igen/gen-semantics.c
Switch the license of all files explicitly copyright the FSF
[thirdparty/binutils-gdb.git] / sim / igen / gen-semantics.c
CommitLineData
feaee4bd
AC
1/* The IGEN simulator generator for GDB, the GNU Debugger.
2
6aba47ca 3 Copyright 2002, 2007 Free Software Foundation, Inc.
feaee4bd
AC
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
4744ac1b 11 the Free Software Foundation; either version 3 of the License, or
feaee4bd
AC
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
4744ac1b 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
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
40static void
41print_semantic_function_header (lf *file,
42 const char *basename,
43 const char *format_name,
44 opcode_bits *expanded_bits,
45 int is_function_definition,
46 int nr_prefetched_words)
47{
48 int indent;
4e0bf4c4 49 lf_printf (file, "\n");
c906108c
SS
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
84void
85print_semantic_declaration (lf *file,
4e0bf4c4 86 insn_entry * insn,
c906108c 87 opcode_bits *expanded_bits,
4e0bf4c4 88 insn_opcodes *opcodes, int nr_prefetched_words)
c906108c
SS
89{
90 print_semantic_function_header (file,
91 insn->name,
92 insn->format_name,
93 expanded_bits,
4e0bf4c4 94 0 /* is not function definition */ ,
c906108c
SS
95 nr_prefetched_words);
96}
4e0bf4c4 97\f
c906108c
SS
98
99
c906108c
SS
100/* generate the semantics.c file */
101
102
103void
4e0bf4c4 104print_idecode_invalid (lf *file, const char *result, invalid_type type)
c906108c
SS
105{
106 const char *name;
107 switch (type)
108 {
4e0bf4c4
AC
109 default:
110 name = "unknown";
111 break;
112 case invalid_illegal:
113 name = "illegal";
114 break;
115 case invalid_fp_unavailable:
116 name = "fp_unavailable";
117 break;
118 case invalid_wrong_slot:
119 name = "wrong_slot";
120 break;
c906108c
SS
121 }
122 if (options.gen.code == generate_jumps)
123 {
124 lf_printf (file, "goto %s_%s;\n",
4e0bf4c4 125 (options.gen.icache ? "icache" : "semantic"), name);
c906108c
SS
126 }
127 else if (options.gen.icache)
128 {
4e0bf4c4
AC
129 lf_printf (file, "%s %sicache_%s (", result,
130 options.module.global.prefix.l, name);
c906108c
SS
131 print_icache_function_actual (file, 0);
132 lf_printf (file, ");\n");
133 }
134 else
135 {
4e0bf4c4
AC
136 lf_printf (file, "%s %ssemantic_%s (", result,
137 options.module.global.prefix.l, name);
c906108c
SS
138 print_semantic_function_actual (file, 0);
139 lf_printf (file, ");\n");
140 }
141}
142
143
144void
145print_semantic_body (lf *file,
4e0bf4c4
AC
146 insn_entry * instruction,
147 opcode_bits *expanded_bits, insn_opcodes *opcodes)
c906108c
SS
148{
149 /* validate the instruction, if a cache this has already been done */
150 if (!options.gen.icache)
151 {
152 print_idecode_validate (file, instruction, opcodes);
153 }
4e0bf4c4
AC
154
155 print_itrace (file, instruction, 0 /*put_value_in_cache */ );
156
c906108c
SS
157 /* generate the instruction profile call - this is delayed until
158 after the instruction has been verified. The count macro
159 generated is prefixed by ITABLE_PREFIX */
160 {
161 lf_printf (file, "\n");
162 lf_indent_suppress (file);
163 lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n",
164 options.module.itable.prefix.u);
165 lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n",
166 options.module.itable.prefix.u);
167 lf_indent_suppress (file);
168 lf_printf (file, "#endif\n");
169 }
170
171 /* generate the model call - this is delayed until after the
172 instruction has been verified */
173 {
174 lf_printf (file, "\n");
175 lf_indent_suppress (file);
176 lf_printf (file, "#if defined (WITH_MON)\n");
177 lf_printf (file, "/* monitoring: */\n");
178 lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
179 lf_printf (file, " mon_issue (");
180 print_function_name (file,
181 instruction->name,
182 instruction->format_name,
4e0bf4c4 183 NULL, NULL, function_name_prefix_itable);
c906108c
SS
184 lf_printf (file, ", cpu, cia);\n");
185 lf_indent_suppress (file);
186 lf_printf (file, "#endif\n");
187 lf_printf (file, "\n");
188 }
4e0bf4c4 189
c906108c
SS
190 /* determine the new instruction address */
191 {
4e0bf4c4 192 lf_printf (file, "/* keep the next instruction address handy */\n");
c906108c
SS
193 if (options.gen.nia == nia_is_invalid)
194 {
4e0bf4c4
AC
195 lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n",
196 options.module.global.prefix.u);
c906108c
SS
197 }
198 else
199 {
200 int nr_immeds = instruction->nr_words - 1;
201 if (options.gen.delayed_branch)
202 {
203 if (nr_immeds > 0)
204 {
205 lf_printf (file, "cia.dp += %d * %d; %s\n",
206 options.insn_bit_size / 8, nr_immeds,
207 "/* skip dp immeds */");
208 }
209 lf_printf (file, "nia.ip = cia.dp; %s\n",
210 "/* instruction pointer */");
211 lf_printf (file, "nia.dp = cia.dp + %d; %s\n",
212 options.insn_bit_size / 8,
213 "/* delayed-slot pointer */");
214 }
215 else
216 {
217 if (nr_immeds > 0)
218 {
219 lf_printf (file, "nia = cia + %d * (%d + 1); %s\n",
220 options.insn_bit_size / 8, nr_immeds,
221 "/* skip immeds as well */");
4e0bf4c4 222
c906108c
SS
223 }
224 else
225 {
226 lf_printf (file, "nia = cia + %d;\n",
227 options.insn_bit_size / 8);
228 }
229 }
230 }
231 }
4e0bf4c4 232
c906108c
SS
233 /* if conditional, generate code to verify that the instruction
234 should be issued */
235 if (filter_is_member (instruction->options, "c")
236 || options.gen.conditional_issue)
237 {
238 lf_printf (file, "\n");
239 lf_printf (file, "/* execute only if conditional passes */\n");
240 lf_printf (file, "if (IS_CONDITION_OK)\n");
241 lf_printf (file, " {\n");
242 lf_indent (file, +4);
243 /* FIXME - need to log a conditional failure */
244 }
4e0bf4c4 245
c906108c
SS
246 /* Architecture expects a REG to be zero. Instead of having to
247 check every read to see if it is refering to that REG just zap it
248 at the start of every instruction */
249 if (options.gen.zero_reg)
250 {
251 lf_printf (file, "\n");
252 lf_printf (file, "/* Architecture expects REG to be zero */\n");
86e0da7a 253 lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
c906108c 254 }
4e0bf4c4 255
c906108c
SS
256 /* generate the code (or at least something */
257 lf_printf (file, "\n");
258 lf_printf (file, "/* semantics: */\n");
259 if (instruction->code != NULL)
260 {
261 /* true code */
262 lf_printf (file, "{\n");
263 lf_indent (file, +2);
264 lf_print__line_ref (file, instruction->code->line);
265 table_print_code (file, instruction->code);
266 lf_indent (file, -2);
267 lf_printf (file, "}\n");
268 lf_print__internal_ref (file);
269 }
270 else if (filter_is_member (instruction->options, "nop"))
271 {
272 lf_print__internal_ref (file);
273 }
274 else
275 {
276 const char *prefix = "sim_engine_abort (";
277 int indent = strlen (prefix);
278 /* abort so it is implemented now */
279 lf_print__line_ref (file, instruction->line);
280 lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
281 lf_indent (file, +indent);
282 lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
283 filter_filename (instruction->line->file_name),
284 instruction->line->line_nr);
285 lf_printf (file, "(long) CIA, \\\n");
286 lf_printf (file, "%sitable[MY_INDEX].name);\n",
287 options.module.itable.prefix.l);
288 lf_indent (file, -indent);
289 lf_print__internal_ref (file);
290 }
4e0bf4c4 291
c906108c
SS
292 /* Close off the conditional execution */
293 if (filter_is_member (instruction->options, "c")
294 || options.gen.conditional_issue)
295 {
296 lf_indent (file, -4);
297 lf_printf (file, " }\n");
4e0bf4c4 298 }
c906108c
SS
299}
300
301static void
302print_c_semantic (lf *file,
4e0bf4c4 303 insn_entry * instruction,
c906108c
SS
304 opcode_bits *expanded_bits,
305 insn_opcodes *opcodes,
4e0bf4c4 306 cache_entry *cache_rules, int nr_prefetched_words)
c906108c 307{
4e0bf4c4 308
c906108c
SS
309 lf_printf (file, "{\n");
310 lf_indent (file, +2);
4e0bf4c4 311
c906108c
SS
312 print_my_defines (file,
313 instruction->name,
4e0bf4c4 314 instruction->format_name, expanded_bits);
c906108c
SS
315 lf_printf (file, "\n");
316 print_icache_body (file,
317 instruction,
318 expanded_bits,
319 cache_rules,
320 (options.gen.direct_access
321 ? define_variables
322 : declare_variables),
323 (options.gen.icache
324 ? get_values_from_icache
4e0bf4c4
AC
325 : do_not_use_icache), nr_prefetched_words);
326
327 lf_printf (file, "%sinstruction_address nia;\n",
328 options.module.global.prefix.l);
329 print_semantic_body (file, instruction, expanded_bits, opcodes);
c906108c 330 lf_printf (file, "return nia;\n");
4e0bf4c4 331
c906108c
SS
332 /* generate something to clean up any #defines created for the cache */
333 if (options.gen.direct_access)
334 {
335 print_icache_body (file,
336 instruction,
337 expanded_bits,
338 cache_rules,
339 undef_variables,
340 (options.gen.icache
341 ? get_values_from_icache
4e0bf4c4 342 : do_not_use_icache), nr_prefetched_words);
c906108c 343 }
4e0bf4c4 344
c906108c
SS
345 lf_indent (file, -2);
346 lf_printf (file, "}\n");
347}
348
349static void
350print_c_semantic_function (lf *file,
4e0bf4c4 351 insn_entry * instruction,
c906108c
SS
352 opcode_bits *expanded_bits,
353 insn_opcodes *opcodes,
4e0bf4c4 354 cache_entry *cache_rules, int nr_prefetched_words)
c906108c
SS
355{
356 /* build the semantic routine to execute the instruction */
357 print_semantic_function_header (file,
358 instruction->name,
359 instruction->format_name,
360 expanded_bits,
4e0bf4c4 361 1 /*is-function-definition */ ,
c906108c
SS
362 nr_prefetched_words);
363 print_c_semantic (file,
364 instruction,
4e0bf4c4 365 expanded_bits, opcodes, cache_rules, nr_prefetched_words);
c906108c
SS
366}
367
368void
369print_semantic_definition (lf *file,
4e0bf4c4 370 insn_entry * insn,
c906108c
SS
371 opcode_bits *expanded_bits,
372 insn_opcodes *opcodes,
4e0bf4c4 373 cache_entry *cache_rules, int nr_prefetched_words)
c906108c
SS
374{
375 print_c_semantic_function (file,
376 insn,
377 expanded_bits,
4e0bf4c4 378 opcodes, cache_rules, nr_prefetched_words);
c906108c 379}