Upload Tizen:Base source
[external/gdb.git] / sim / igen / gen-semantics.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3    Copyright 2002, 2007, 2008, 2009, 2010 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                                 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                             insn_entry * insn,
87                             opcode_bits *expanded_bits,
88                             insn_opcodes *opcodes, 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 \f
98
99
100 /* generate the semantics.c file */
101
102
103 void
104 print_idecode_invalid (lf *file, const char *result, invalid_type type)
105 {
106   const char *name;
107   switch (type)
108     {
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;
121     }
122   if (options.gen.code == generate_jumps)
123     {
124       lf_printf (file, "goto %s_%s;\n",
125                  (options.gen.icache ? "icache" : "semantic"), name);
126     }
127   else if (options.gen.icache)
128     {
129       lf_printf (file, "%s %sicache_%s (", result,
130                  options.module.global.prefix.l, name);
131       print_icache_function_actual (file, 0);
132       lf_printf (file, ");\n");
133     }
134   else
135     {
136       lf_printf (file, "%s %ssemantic_%s (", result,
137                  options.module.global.prefix.l, name);
138       print_semantic_function_actual (file, 0);
139       lf_printf (file, ");\n");
140     }
141 }
142
143
144 void
145 print_semantic_body (lf *file,
146                      insn_entry * instruction,
147                      opcode_bits *expanded_bits, insn_opcodes *opcodes)
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     }
154
155   print_itrace (file, instruction, 0 /*put_value_in_cache */ );
156
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,
183                          NULL, NULL, function_name_prefix_itable);
184     lf_printf (file, ", cpu, cia);\n");
185     lf_indent_suppress (file);
186     lf_printf (file, "#endif\n");
187     lf_printf (file, "\n");
188   }
189
190   /* determine the new instruction address */
191   {
192     lf_printf (file, "/* keep the next instruction address handy */\n");
193     if (options.gen.nia == nia_is_invalid)
194       {
195         lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n",
196                    options.module.global.prefix.u);
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 */");
222
223               }
224             else
225               {
226                 lf_printf (file, "nia = cia + %d;\n",
227                            options.insn_bit_size / 8);
228               }
229           }
230       }
231   }
232
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     }
245
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");
253       lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
254     }
255
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     }
291
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");
298     }
299 }
300
301 static void
302 print_c_semantic (lf *file,
303                   insn_entry * instruction,
304                   opcode_bits *expanded_bits,
305                   insn_opcodes *opcodes,
306                   cache_entry *cache_rules, int nr_prefetched_words)
307 {
308
309   lf_printf (file, "{\n");
310   lf_indent (file, +2);
311
312   print_my_defines (file,
313                     instruction->name,
314                     instruction->format_name, expanded_bits);
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
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);
330   lf_printf (file, "return nia;\n");
331
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
342                           : do_not_use_icache), nr_prefetched_words);
343     }
344
345   lf_indent (file, -2);
346   lf_printf (file, "}\n");
347 }
348
349 static void
350 print_c_semantic_function (lf *file,
351                            insn_entry * instruction,
352                            opcode_bits *expanded_bits,
353                            insn_opcodes *opcodes,
354                            cache_entry *cache_rules, int nr_prefetched_words)
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,
361                                   1 /*is-function-definition */ ,
362                                   nr_prefetched_words);
363   print_c_semantic (file,
364                     instruction,
365                     expanded_bits, opcodes, cache_rules, nr_prefetched_words);
366 }
367
368 void
369 print_semantic_definition (lf *file,
370                            insn_entry * insn,
371                            opcode_bits *expanded_bits,
372                            insn_opcodes *opcodes,
373                            cache_entry *cache_rules, int nr_prefetched_words)
374 {
375   print_c_semantic_function (file,
376                              insn,
377                              expanded_bits,
378                              opcodes, cache_rules, nr_prefetched_words);
379 }