Don't bother generating trace prefix string when not tracing.
[external/binutils.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