Don't run ld-scripts/pr20302 on linuxaout
[external/binutils.git] / sim / igen / gen-engine.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3    Copyright 2002-2016 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 #include "misc.h"
23 #include "lf.h"
24 #include "table.h"
25 #include "filter.h"
26
27 #include "igen.h"
28
29 #include "ld-insn.h"
30 #include "ld-decode.h"
31
32 #include "gen.h"
33
34 #include "gen-idecode.h"
35 #include "gen-engine.h"
36 #include "gen-icache.h"
37 #include "gen-semantics.h"
38
39
40 static void
41 print_engine_issue_prefix_hook (lf *file)
42 {
43   lf_printf (file, "\n");
44   lf_indent_suppress (file);
45   lf_printf (file, "#if defined (ENGINE_ISSUE_PREFIX_HOOK)\n");
46   lf_printf (file, "ENGINE_ISSUE_PREFIX_HOOK();\n");
47   lf_indent_suppress (file);
48   lf_printf (file, "#endif\n");
49   lf_printf (file, "\n");
50 }
51
52 static void
53 print_engine_issue_postfix_hook (lf *file)
54 {
55   lf_printf (file, "\n");
56   lf_indent_suppress (file);
57   lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n");
58   lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n");
59   lf_indent_suppress (file);
60   lf_printf (file, "#endif\n");
61   lf_printf (file, "\n");
62 }
63
64
65 static void
66 print_run_body (lf *file, gen_entry *table)
67 {
68   /* Output the function to execute real code:
69
70      Unfortunatly, there are multiple cases to consider vis:
71
72      <icache> X <smp>
73
74      Consequently this function is written in multiple different ways */
75
76   lf_printf (file, "{\n");
77   lf_indent (file, +2);
78   if (!options.gen.smp)
79     {
80       lf_printf (file, "%sinstruction_address cia;\n",
81                  options.module.global.prefix.l);
82     }
83   lf_printf (file, "int current_cpu = next_cpu_nr;\n");
84
85   if (options.gen.icache)
86     {
87       lf_printf (file, "/* flush the icache of a possible break insn */\n");
88       lf_printf (file, "{\n");
89       lf_printf (file, "  int cpu_nr;\n");
90       lf_printf (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
91       lf_printf (file, "    cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
92       lf_printf (file, "}\n");
93     }
94
95   if (!options.gen.smp)
96     {
97
98       lf_putstr (file, "\
99 /* CASE 1: NO SMP (with or with out instruction cache).\n\
100 \n\
101 In this case, we can take advantage of the fact that the current\n\
102 instruction address (CIA) does not need to be read from / written to\n\
103 the CPU object after the execution of an instruction.\n\
104 \n\
105 Instead, CIA is only saved when the main loop exits.  This occures\n\
106 when either sim_engine_halt or sim_engine_restart is called.  Both of\n\
107 these functions save the current instruction address before halting /\n\
108 restarting the simulator.\n\
109 \n\
110 As a variation, there may also be support for an instruction cracking\n\
111 cache. */\n\
112 \n\
113 ");
114
115       lf_putstr (file, "\n");
116       lf_putstr (file, "/* prime the main loop */\n");
117       lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
118       lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
119       lf_putstr (file, "cia = CPU_PC_GET (CPU);\n");
120
121       lf_putstr (file, "\n");
122       lf_putstr (file, "while (1)\n");
123       lf_putstr (file, "  {\n");
124       lf_indent (file, +4);
125
126       lf_printf (file, "%sinstruction_address nia;\n",
127                  options.module.global.prefix.l);
128
129       lf_printf (file, "\n");
130       if (!options.gen.icache)
131         {
132           lf_printf (file,
133                      "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
134                      options.module.global.prefix.l, options.insn_bit_size);
135           print_engine_issue_prefix_hook (file);
136           print_idecode_body (file, table, "nia = ");
137           print_engine_issue_postfix_hook (file);
138         }
139       else
140         {
141           lf_putstr (file, "idecode_cache *cache_entry =\n");
142           lf_putstr (file, "  cpu_icache_entry (cpu, cia);\n");
143           lf_putstr (file, "if (cache_entry->address == cia)\n");
144           lf_putstr (file, "  {\n");
145           lf_indent (file, -4);
146           lf_putstr (file, "/* cache hit */\n");
147           lf_putstr (file,
148                      "idecode_semantic *const semantic = cache_entry->semantic;\n");
149           lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
150           /* tail */
151           lf_indent (file, -4);
152           lf_putstr (file, "  }\n");
153           lf_putstr (file, "else\n");
154           lf_putstr (file, "  {\n");
155           lf_indent (file, +4);
156           lf_putstr (file, "/* cache miss */\n");
157           if (!options.gen.semantic_icache)
158             {
159               lf_putstr (file, "idecode_semantic *semantic;\n");
160             }
161           lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
162                      options.insn_bit_size);
163           lf_putstr (file, "if (WITH_MON != 0)\n");
164           lf_putstr (file,
165                      "  mon_event (mon_event_icache_miss, cpu, cia);\n");
166           if (options.gen.semantic_icache)
167             {
168               lf_putstr (file, "{\n");
169               lf_indent (file, +2);
170               print_engine_issue_prefix_hook (file);
171               print_idecode_body (file, table, "nia =");
172               print_engine_issue_postfix_hook (file);
173               lf_indent (file, -2);
174               lf_putstr (file, "}\n");
175             }
176           else
177             {
178               print_engine_issue_prefix_hook (file);
179               print_idecode_body (file, table, "semantic =");
180               lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
181               print_engine_issue_postfix_hook (file);
182             }
183           lf_indent (file, -4);
184           lf_putstr (file, "  }\n");
185         }
186
187       /* update the cpu if necessary */
188       switch (options.gen.nia)
189         {
190         case nia_is_cia_plus_one:
191           lf_printf (file, "\n");
192           lf_printf (file, "/* Update the instruction address */\n");
193           lf_printf (file, "cia = nia;\n");
194           break;
195         case nia_is_void:
196         case nia_is_invalid:
197           ERROR ("engine gen when NIA complex");
198         }
199
200       /* events */
201       lf_putstr (file, "\n");
202       lf_putstr (file, "/* process any events */\n");
203       lf_putstr (file, "if (sim_events_tick (sd))\n");
204       lf_putstr (file, "  {\n");
205       lf_putstr (file, "    CPU_PC_SET (CPU, cia);\n");
206       lf_putstr (file, "    sim_events_process (sd);\n");
207       lf_putstr (file, "    cia = CPU_PC_GET (CPU);\n");
208       lf_putstr (file, "  }\n");
209
210       lf_indent (file, -4);
211       lf_printf (file, "  }\n");
212     }
213
214   if (options.gen.smp)
215     {
216
217       lf_putstr (file, "\
218 /* CASE 2: SMP (With or without ICACHE)\n\
219 \n\
220 The complexity here comes from needing to correctly halt the simulator\n\
221 when it is aborted.  For instance, if cpu0 requests a restart then\n\
222 cpu1 will normally be the next cpu that is run.  Cpu0 being restarted\n\
223 after all the other CPU's and the event queue have been processed */\n\
224 \n\
225 ");
226
227       lf_putstr (file, "\n");
228       lf_printf (file,
229                  "/* have ensured that the event queue is NOT next */\n");
230       lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
231       lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
232       lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
233
234       lf_putstr (file, "\n");
235       lf_putstr (file, "while (1)\n");
236       lf_putstr (file, "  {\n");
237       lf_indent (file, +4);
238       lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
239       lf_putstr (file, "instruction_address cia = CPU_PC_GET (cpu);\n");
240       lf_putstr (file, "\n");
241
242       if (!options.gen.icache)
243         {
244           lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n",
245                      options.insn_bit_size);
246           print_engine_issue_prefix_hook (file);
247           print_idecode_body (file, table, "cia =");
248           lf_putstr (file, "CPU_PC_SET (cpu, cia);\n");
249           print_engine_issue_postfix_hook (file);
250         }
251
252       if (options.gen.icache)
253         {
254           lf_putstr (file, "engine_cache *cache_entry =\n");
255           lf_putstr (file, "  cpu_icache_entry(processor, cia);\n");
256           lf_putstr (file, "\n");
257           lf_putstr (file, "if (cache_entry->address == cia) {\n");
258           {
259             lf_indent (file, +2);
260             lf_putstr (file, "\n");
261             lf_putstr (file, "/* cache hit */\n");
262             lf_putstr (file,
263                        "engine_semantic *semantic = cache_entry->semantic;\n");
264             lf_putstr (file,
265                        "cia = semantic(processor, cache_entry, cia);\n");
266             /* tail */
267             lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
268             lf_putstr (file, "\n");
269             lf_indent (file, -2);
270           }
271           lf_putstr (file, "}\n");
272           lf_putstr (file, "else {\n");
273           {
274             lf_indent (file, +2);
275             lf_putstr (file, "\n");
276             lf_putstr (file, "/* cache miss */\n");
277             if (!options.gen.semantic_icache)
278               {
279                 lf_putstr (file, "engine_semantic *semantic;\n");
280               }
281             lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
282                        options.insn_bit_size);
283             lf_putstr (file, "if (WITH_MON != 0)\n");
284             lf_putstr (file,
285                        "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
286             if (options.gen.semantic_icache)
287               {
288                 lf_putstr (file, "{\n");
289                 lf_indent (file, +2);
290                 print_engine_issue_prefix_hook (file);
291                 print_idecode_body (file, table, "cia =");
292                 print_engine_issue_postfix_hook (file);
293                 lf_indent (file, -2);
294                 lf_putstr (file, "}\n");
295               }
296             else
297               {
298                 print_engine_issue_prefix_hook (file);
299                 print_idecode_body (file, table, "semantic = ");
300                 lf_putstr (file,
301                            "cia = semantic(processor, cache_entry, cia);\n");
302                 print_engine_issue_postfix_hook (file);
303               }
304             /* tail */
305             lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
306             lf_putstr (file, "\n");
307             lf_indent (file, -2);
308           }
309           lf_putstr (file, "}\n");
310         }
311
312       lf_putstr (file, "\n");
313       lf_putstr (file, "current_cpu += 1;\n");
314       lf_putstr (file, "if (current_cpu == nr_cpus)\n");
315       lf_putstr (file, "  {\n");
316       lf_putstr (file, "    if (sim_events_tick (sd))\n");
317       lf_putstr (file, "      {\n");
318       lf_putstr (file, "        sim_events_process (sd);\n");
319       lf_putstr (file, "      }\n");
320       lf_putstr (file, "    current_cpu = 0;\n");
321       lf_putstr (file, "  }\n");
322
323       /* tail */
324       lf_indent (file, -4);
325       lf_putstr (file, "  }\n");
326     }
327
328
329   lf_indent (file, -2);
330   lf_putstr (file, "}\n");
331 }
332
333
334 /****************************************************************/
335
336 void
337 print_engine_run_function_header (lf *file,
338                                   char *processor,
339                                   function_decl_type decl_type)
340 {
341   int indent;
342   lf_printf (file, "\n");
343   switch (decl_type)
344     {
345     case is_function_declaration:
346       lf_print__function_type (file, "void", "INLINE_ENGINE", "\n");
347       break;
348     case is_function_definition:
349       lf_print__function_type (file, "void", "INLINE_ENGINE", " ");
350       break;
351     case is_function_variable:
352       lf_printf (file, "void (*");
353       break;
354     }
355   indent = print_function_name (file, "run", NULL,      /* format name */
356                                 processor, NULL,        /* expanded bits */
357                                 function_name_prefix_engine);
358   switch (decl_type)
359     {
360     case is_function_definition:
361       lf_putstr (file, "\n(");
362       indent = 1;
363       break;
364     case is_function_declaration:
365       indent += lf_printf (file, " (");
366       break;
367     case is_function_variable:
368       lf_putstr (file, ")\n(");
369       indent = 1;
370       break;
371     }
372   lf_indent (file, +indent);
373   lf_printf (file, "SIM_DESC sd,\n");
374   lf_printf (file, "int next_cpu_nr,\n");
375   lf_printf (file, "int nr_cpus,\n");
376   lf_printf (file, "int siggnal)");
377   lf_indent (file, -indent);
378   switch (decl_type)
379     {
380     case is_function_definition:
381       lf_putstr (file, "\n");
382       break;
383     case is_function_variable:
384     case is_function_declaration:
385       lf_putstr (file, ";\n");
386       break;
387     }
388 }
389
390
391 void
392 gen_engine_h (lf *file,
393               gen_table *gen, insn_table *isa, cache_entry *cache_rules)
394 {
395   gen_list *entry;
396   for (entry = gen->tables; entry != NULL; entry = entry->next)
397     {
398       print_engine_run_function_header (file,
399                                         (options.gen.multi_sim
400                                          ? entry->model->name
401                                          : NULL), is_function_declaration);
402     }
403 }
404
405
406 void
407 gen_engine_c (lf *file,
408               gen_table *gen, insn_table *isa, cache_entry *cache_rules)
409 {
410   gen_list *entry;
411   /* the intro */
412   print_includes (file);
413   print_include_inline (file, options.module.semantics);
414   print_include (file, options.module.engine);
415   lf_printf (file, "\n");
416   lf_printf (file, "#include \"sim-assert.h\"\n");
417   lf_printf (file, "\n");
418   print_idecode_globals (file);
419   lf_printf (file, "\n");
420
421   for (entry = gen->tables; entry != NULL; entry = entry->next)
422     {
423       switch (options.gen.code)
424         {
425         case generate_calls:
426           print_idecode_lookups (file, entry->table, cache_rules);
427
428           /* output the main engine routine */
429           print_engine_run_function_header (file,
430                                             (options.gen.multi_sim
431                                              ? entry->model->name
432                                              : NULL), is_function_definition);
433           print_run_body (file, entry->table);
434           break;
435
436         case generate_jumps:
437           ERROR ("Jumps currently unimplemented");
438           break;
439         }
440     }
441 }