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