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 3 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, see <http://www.gnu.org/licenses/>.
17 
18     */
19 
20 
21 
22 #include "misc.h"
23 #include "lf.h"
24 #include "lf-ppc.h"
25 #include "table.h"
26 #include "filter.h"
27 #include "filter-ppc.h"
28 
29 #include "ld-decode.h"
30 #include "ld-cache.h"
31 #include "ld-insn.h"
32 
33 #include "igen.h"
34 
35 #include "gen-semantics.h"
36 #include "gen-icache.h"
37 #include "gen-idecode.h"
38 
39 
40 static void
print_semantic_function_header(lf * file,const char * basename,insn_bits * expanded_bits,int is_function_definition)41 print_semantic_function_header(lf *file,
42                                      const char *basename,
43                                      insn_bits *expanded_bits,
44                                      int is_function_definition)
45 {
46   int indent;
47   lf_printf(file, "\n");
48   lf_print__function_type(file, SEMANTIC_FUNCTION_TYPE, "PSIM_EXTERN_SEMANTICS",
49                                (is_function_definition ? "\n" : " "));
50   indent = print_function_name(file,
51                                      basename,
52                                      expanded_bits,
53                                      function_name_prefix_semantics);
54   if (is_function_definition)
55     lf_indent(file, +indent);
56   else
57     lf_printf(file, "\n");
58   lf_printf(file, "(%s)", SEMANTIC_FUNCTION_FORMAL);
59   if (is_function_definition)
60     lf_indent(file, -indent);
61   else
62     lf_printf(file, ";");
63   lf_printf(file, "\n");
64 }
65 
66 void
print_semantic_declaration(insn_table * entry,lf * file,void * data,insn * instruction,int depth)67 print_semantic_declaration(insn_table *entry,
68                                  lf *file,
69                                  void *data,
70                                  insn *instruction,
71                                  int depth)
72 {
73   if (generate_expanded_instructions) {
74     ASSERT(entry->nr_insn == 1);
75     print_semantic_function_header(file,
76                                            instruction->file_entry->fields[insn_name],
77                                            entry->expanded_bits,
78                                            0/* is not function definition*/);
79   }
80   else {
81     print_semantic_function_header(file,
82                                            instruction->file_entry->fields[insn_name],
83                                            NULL,
84                                            0/* is not function definition*/);
85   }
86 }
87 
88 
89 
90 /* generate the semantics.c file */
91 
92 
93 void
print_idecode_illegal(lf * file,const char * result)94 print_idecode_illegal(lf *file,
95                           const char *result)
96 {
97   if ((code & generate_jumps))
98     lf_printf(file, "goto %s_illegal;\n", (code & generate_with_icache) ? "icache" : "semantic");
99   else if ((code & generate_with_icache))
100     lf_printf(file, "%s icache_illegal(%s);\n", result, ICACHE_FUNCTION_ACTUAL);
101   else
102     lf_printf(file, "%s semantic_illegal(%s);\n", result, SEMANTIC_FUNCTION_ACTUAL);
103 }
104 
105 
106 void
print_semantic_body(lf * file,insn * instruction,insn_bits * expanded_bits,opcode_field * opcodes)107 print_semantic_body(lf *file,
108                         insn *instruction,
109                         insn_bits *expanded_bits,
110                         opcode_field *opcodes)
111 {
112   print_itrace(file, instruction->file_entry, 0/*put_value_in_cache*/);
113 
114   /* validate the instruction, if a cache this has already been done */
115   if (!(code & generate_with_icache))
116     print_idecode_validate(file, instruction, opcodes);
117 
118   /* generate the profiling call - this is delayed until after the
119      instruction has been verified */
120   lf_printf(file, "\n");
121   lf_printf(file, "/* monitoring: */\n");
122   lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n");
123   lf_printf(file, "  mon_issue(");
124   print_function_name(file,
125                           instruction->file_entry->fields[insn_name],
126                           NULL,
127                           function_name_prefix_itable);
128   lf_printf(file, ", processor, cia);\n");
129   lf_printf(file, "}\n");
130 
131   /* generate the code (or at least something */
132   lf_printf(file, "\n");
133   lf_printf(file, "/* semantics: */\n");
134   lf_printf(file, "nia = cia + %d;\n", insn_bit_size / 8);
135   if (instruction->file_entry->annex != NULL) {
136     /* true code */
137     table_entry_print_cpp_line_nr(file, instruction->file_entry);
138     lf_printf(file, "{\n");
139     lf_indent(file, +2);
140     lf_print__c_code(file, instruction->file_entry->annex);
141     lf_indent(file, -2);
142     lf_printf(file, "}\n");
143     lf_print__internal_ref(file);
144   }
145   else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
146     lf_print__internal_ref(file);
147   }
148   else {
149     /* abort so it is implemented now */
150     table_entry_print_cpp_line_nr(file, instruction->file_entry);
151     lf_putstr(file, "error(\"%s:%d:0x%08lx:%s unimplemented\\n\",\n");
152     lf_printf(file, "      itable[MY_INDEX].file, itable[MY_INDEX].line_nr, (long)cia, itable[MY_INDEX].name);\n");
153     lf_print__internal_ref(file);
154   }
155 }
156 
157 static void
print_c_semantic(lf * file,insn * instruction,insn_bits * expanded_bits,opcode_field * opcodes,cache_table * cache_rules)158 print_c_semantic(lf *file,
159                      insn *instruction,
160                      insn_bits *expanded_bits,
161                      opcode_field *opcodes,
162                      cache_table *cache_rules)
163 {
164 
165   lf_printf(file, "{\n");
166   lf_indent(file, +2);
167 
168   print_my_defines(file, expanded_bits, instruction->file_entry);
169   lf_printf(file, "\n");
170   print_icache_body(file,
171                         instruction,
172                         expanded_bits,
173                         cache_rules,
174                         ((code & generate_with_direct_access)
175                          ? define_variables
176                          : declare_variables),
177                         ((code & generate_with_icache)
178                          ? get_values_from_icache
179                          : do_not_use_icache));
180 
181   lf_printf(file, "unsigned_word nia;\n");
182   print_semantic_body(file,
183                           instruction,
184                           expanded_bits,
185                           opcodes);
186   lf_printf(file, "return nia;\n");
187 
188   /* generate something to clean up any #defines created for the cache */
189   if (code & generate_with_direct_access)
190     print_icache_body(file,
191                           instruction,
192                           expanded_bits,
193                           cache_rules,
194                           undef_variables,
195                           ((code & generate_with_icache)
196                            ? get_values_from_icache
197                            : do_not_use_icache));
198 
199   lf_indent(file, -2);
200   lf_printf(file, "}\n");
201 }
202 
203 static void
print_c_semantic_function(lf * file,insn * instruction,insn_bits * expanded_bits,opcode_field * opcodes,cache_table * cache_rules)204 print_c_semantic_function(lf *file,
205                                 insn *instruction,
206                                 insn_bits *expanded_bits,
207                                 opcode_field *opcodes,
208                                 cache_table *cache_rules)
209 {
210   /* build the semantic routine to execute the instruction */
211   print_semantic_function_header(file,
212                                          instruction->file_entry->fields[insn_name],
213                                          expanded_bits,
214                                          1/*is-function-definition*/);
215   print_c_semantic(file,
216                        instruction,
217                        expanded_bits,
218                        opcodes,
219                        cache_rules);
220 }
221 
222 void
print_semantic_definition(insn_table * entry,lf * file,void * data,insn * instruction,int depth)223 print_semantic_definition(insn_table *entry,
224                                 lf *file,
225                                 void *data,
226                                 insn *instruction,
227                                 int depth)
228 {
229   cache_table *cache_rules = (cache_table*)data;
230   if (generate_expanded_instructions) {
231     ASSERT(entry->nr_insn == 1
232              && entry->opcode == NULL
233              && entry->parent != NULL
234              && entry->parent->opcode != NULL);
235     ASSERT(entry->nr_insn == 1
236              && entry->opcode == NULL
237              && entry->parent != NULL
238              && entry->parent->opcode != NULL
239              && entry->parent->opcode_rule != NULL);
240     print_c_semantic_function(file,
241                                     entry->insns,
242                                     entry->expanded_bits,
243                                     entry->parent->opcode,
244                                     cache_rules);
245   }
246   else {
247     print_c_semantic_function(file, instruction,
248                                     NULL, NULL,
249                                     cache_rules);
250   }
251 }
252