76c4d14cb4fa541d221928d6299731d2897c01b2
[external/binutils.git] / sim / igen / gen-semantics.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3    Copyright 2002, 2007 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 2 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, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23
24
25
26 #include "misc.h"
27 #include "lf.h"
28 #include "table.h"
29 #include "filter.h"
30 #include "igen.h"
31
32 #include "ld-insn.h"
33 #include "ld-decode.h"
34
35 #include "gen.h"
36
37 #include "gen-semantics.h"
38 #include "gen-icache.h"
39 #include "gen-idecode.h"
40
41
42 static void
43 print_semantic_function_header (lf *file,
44                                 const char *basename,
45                                 const char *format_name,
46                                 opcode_bits *expanded_bits,
47                                 int is_function_definition,
48                                 int nr_prefetched_words)
49 {
50   int indent;
51   lf_printf (file, "\n");
52   lf_print__function_type_function (file, print_semantic_function_type,
53                                     "EXTERN_SEMANTICS",
54                                     (is_function_definition ? "\n" : " "));
55   indent = print_function_name (file,
56                                 basename,
57                                 format_name,
58                                 NULL,
59                                 expanded_bits,
60                                 function_name_prefix_semantics);
61   if (is_function_definition)
62     {
63       indent += lf_printf (file, " ");
64       lf_indent (file, +indent);
65     }
66   else
67     {
68       lf_printf (file, "\n");
69     }
70   lf_printf (file, "(");
71   lf_indent (file, +1);
72   print_semantic_function_formal (file, nr_prefetched_words);
73   lf_indent (file, -1);
74   lf_printf (file, ")");
75   if (is_function_definition)
76     {
77       lf_indent (file, -indent);
78     }
79   else
80     {
81       lf_printf (file, ";");
82     }
83   lf_printf (file, "\n");
84 }
85
86 void
87 print_semantic_declaration (lf *file,
88                             insn_entry * insn,
89                             opcode_bits *expanded_bits,
90                             insn_opcodes *opcodes, int nr_prefetched_words)
91 {
92   print_semantic_function_header (file,
93                                   insn->name,
94                                   insn->format_name,
95                                   expanded_bits,
96                                   0 /* is not function definition */ ,
97                                   nr_prefetched_words);
98 }
99 \f
100
101
102 /* generate the semantics.c file */
103
104
105 void
106 print_idecode_invalid (lf *file, const char *result, invalid_type type)
107 {
108   const char *name;
109   switch (type)
110     {
111     default:
112       name = "unknown";
113       break;
114     case invalid_illegal:
115       name = "illegal";
116       break;
117     case invalid_fp_unavailable:
118       name = "fp_unavailable";
119       break;
120     case invalid_wrong_slot:
121       name = "wrong_slot";
122       break;
123     }
124   if (options.gen.code == generate_jumps)
125     {
126       lf_printf (file, "goto %s_%s;\n",
127                  (options.gen.icache ? "icache" : "semantic"), name);
128     }
129   else if (options.gen.icache)
130     {
131       lf_printf (file, "%s %sicache_%s (", result,
132                  options.module.global.prefix.l, name);
133       print_icache_function_actual (file, 0);
134       lf_printf (file, ");\n");
135     }
136   else
137     {
138       lf_printf (file, "%s %ssemantic_%s (", result,
139                  options.module.global.prefix.l, name);
140       print_semantic_function_actual (file, 0);
141       lf_printf (file, ");\n");
142     }
143 }
144
145
146 void
147 print_semantic_body (lf *file,
148                      insn_entry * instruction,
149                      opcode_bits *expanded_bits, 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       lf_indent (file, +2);
266       lf_print__line_ref (file, instruction->code->line);
267       table_print_code (file, instruction->code);
268       lf_indent (file, -2);
269       lf_printf (file, "}\n");
270       lf_print__internal_ref (file);
271     }
272   else if (filter_is_member (instruction->options, "nop"))
273     {
274       lf_print__internal_ref (file);
275     }
276   else
277     {
278       const char *prefix = "sim_engine_abort (";
279       int indent = strlen (prefix);
280       /* abort so it is implemented now */
281       lf_print__line_ref (file, instruction->line);
282       lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
283       lf_indent (file, +indent);
284       lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
285                  filter_filename (instruction->line->file_name),
286                  instruction->line->line_nr);
287       lf_printf (file, "(long) CIA, \\\n");
288       lf_printf (file, "%sitable[MY_INDEX].name);\n",
289                  options.module.itable.prefix.l);
290       lf_indent (file, -indent);
291       lf_print__internal_ref (file);
292     }
293
294   /* Close off the conditional execution */
295   if (filter_is_member (instruction->options, "c")
296       || options.gen.conditional_issue)
297     {
298       lf_indent (file, -4);
299       lf_printf (file, "  }\n");
300     }
301 }
302
303 static void
304 print_c_semantic (lf *file,
305                   insn_entry * instruction,
306                   opcode_bits *expanded_bits,
307                   insn_opcodes *opcodes,
308                   cache_entry *cache_rules, int nr_prefetched_words)
309 {
310
311   lf_printf (file, "{\n");
312   lf_indent (file, +2);
313
314   print_my_defines (file,
315                     instruction->name,
316                     instruction->format_name, expanded_bits);
317   lf_printf (file, "\n");
318   print_icache_body (file,
319                      instruction,
320                      expanded_bits,
321                      cache_rules,
322                      (options.gen.direct_access
323                       ? define_variables
324                       : declare_variables),
325                      (options.gen.icache
326                       ? get_values_from_icache
327                       : do_not_use_icache), nr_prefetched_words);
328
329   lf_printf (file, "%sinstruction_address nia;\n",
330              options.module.global.prefix.l);
331   print_semantic_body (file, instruction, expanded_bits, opcodes);
332   lf_printf (file, "return nia;\n");
333
334   /* generate something to clean up any #defines created for the cache */
335   if (options.gen.direct_access)
336     {
337       print_icache_body (file,
338                          instruction,
339                          expanded_bits,
340                          cache_rules,
341                          undef_variables,
342                          (options.gen.icache
343                           ? get_values_from_icache
344                           : do_not_use_icache), nr_prefetched_words);
345     }
346
347   lf_indent (file, -2);
348   lf_printf (file, "}\n");
349 }
350
351 static void
352 print_c_semantic_function (lf *file,
353                            insn_entry * instruction,
354                            opcode_bits *expanded_bits,
355                            insn_opcodes *opcodes,
356                            cache_entry *cache_rules, int nr_prefetched_words)
357 {
358   /* build the semantic routine to execute the instruction */
359   print_semantic_function_header (file,
360                                   instruction->name,
361                                   instruction->format_name,
362                                   expanded_bits,
363                                   1 /*is-function-definition */ ,
364                                   nr_prefetched_words);
365   print_c_semantic (file,
366                     instruction,
367                     expanded_bits, opcodes, cache_rules, nr_prefetched_words);
368 }
369
370 void
371 print_semantic_definition (lf *file,
372                            insn_entry * insn,
373                            opcode_bits *expanded_bits,
374                            insn_opcodes *opcodes,
375                            cache_entry *cache_rules, int nr_prefetched_words)
376 {
377   print_c_semantic_function (file,
378                              insn,
379                              expanded_bits,
380                              opcodes, cache_rules, nr_prefetched_words);
381 }