1 |
106 |
markom |
/* 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 |
|
|
#include "misc.h"
|
23 |
|
|
#include "lf.h"
|
24 |
|
|
#include "table.h"
|
25 |
|
|
|
26 |
|
|
#include "filter.h"
|
27 |
|
|
|
28 |
|
|
#include "ld-decode.h"
|
29 |
|
|
#include "ld-cache.h"
|
30 |
|
|
#include "ld-insn.h"
|
31 |
|
|
|
32 |
|
|
#include "igen.h"
|
33 |
|
|
|
34 |
|
|
#include "gen-semantics.h"
|
35 |
|
|
#include "gen-idecode.h"
|
36 |
|
|
#include "gen-icache.h"
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
|
40 |
|
|
static void
|
41 |
|
|
print_icache_function_header(lf *file,
|
42 |
|
|
const char *basename,
|
43 |
|
|
insn_bits *expanded_bits,
|
44 |
|
|
int is_function_definition)
|
45 |
|
|
{
|
46 |
|
|
lf_printf(file, "\n");
|
47 |
|
|
lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
|
48 |
|
|
print_function_name(file,
|
49 |
|
|
basename,
|
50 |
|
|
expanded_bits,
|
51 |
|
|
function_name_prefix_icache);
|
52 |
|
|
lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
|
53 |
|
|
if (!is_function_definition)
|
54 |
|
|
lf_printf(file, ";");
|
55 |
|
|
lf_printf(file, "\n");
|
56 |
|
|
}
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
void
|
60 |
|
|
print_icache_declaration(insn_table *entry,
|
61 |
|
|
lf *file,
|
62 |
|
|
void *data,
|
63 |
|
|
insn *instruction,
|
64 |
|
|
int depth)
|
65 |
|
|
{
|
66 |
|
|
if (generate_expanded_instructions) {
|
67 |
|
|
ASSERT(entry->nr_insn == 1);
|
68 |
|
|
print_icache_function_header(file,
|
69 |
|
|
entry->insns->file_entry->fields[insn_name],
|
70 |
|
|
entry->expanded_bits,
|
71 |
|
|
0/* is not function definition */);
|
72 |
|
|
}
|
73 |
|
|
else {
|
74 |
|
|
print_icache_function_header(file,
|
75 |
|
|
instruction->file_entry->fields[insn_name],
|
76 |
|
|
NULL,
|
77 |
|
|
0/* is not function definition */);
|
78 |
|
|
}
|
79 |
|
|
}
|
80 |
|
|
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
static void
|
84 |
|
|
print_icache_extraction(lf *file,
|
85 |
|
|
insn *instruction,
|
86 |
|
|
const char *entry_name,
|
87 |
|
|
const char *entry_type,
|
88 |
|
|
const char *entry_expression,
|
89 |
|
|
const char *original_name,
|
90 |
|
|
const char *file_name,
|
91 |
|
|
int line_nr,
|
92 |
|
|
insn_field *cur_field,
|
93 |
|
|
insn_bits *bits,
|
94 |
|
|
icache_decl_type what_to_declare,
|
95 |
|
|
icache_body_type what_to_do,
|
96 |
|
|
const char *reason)
|
97 |
|
|
{
|
98 |
|
|
const char *expression;
|
99 |
|
|
ASSERT(entry_name != NULL);
|
100 |
|
|
|
101 |
|
|
/* Define a storage area for the cache element */
|
102 |
|
|
if (what_to_declare == undef_variables) {
|
103 |
|
|
/* We've finished with the value - destory it */
|
104 |
|
|
lf_indent_suppress(file);
|
105 |
|
|
lf_printf(file, "#undef %s\n", entry_name);
|
106 |
|
|
return;
|
107 |
|
|
}
|
108 |
|
|
else if (what_to_declare == define_variables) {
|
109 |
|
|
lf_indent_suppress(file);
|
110 |
|
|
lf_printf(file, "#define %s ", entry_name);
|
111 |
|
|
}
|
112 |
|
|
else {
|
113 |
|
|
if (file_name != NULL)
|
114 |
|
|
lf_print__external_reference(file, line_nr, file_name);
|
115 |
|
|
lf_printf(file, "%s const %s UNUSED = ",
|
116 |
|
|
entry_type == NULL ? "unsigned" : entry_type,
|
117 |
|
|
entry_name);
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
/* define a value for that storage area as determined by what is in
|
121 |
|
|
the cache */
|
122 |
|
|
if (bits != NULL
|
123 |
|
|
&& strcmp(entry_name, cur_field->val_string) == 0
|
124 |
|
|
&& ((bits->opcode->is_boolean && bits->value == 0)
|
125 |
|
|
|| (!bits->opcode->is_boolean))) {
|
126 |
|
|
/* The simple field has been made constant (as a result of
|
127 |
|
|
expanding instructions or similar). Remember that for a
|
128 |
|
|
boolean field, value is either 0 (implying the required
|
129 |
|
|
boolean_constant) or nonzero (implying some other value and
|
130 |
|
|
handled later below) - Define the variable accordingly */
|
131 |
|
|
expression = "constant field";
|
132 |
|
|
ASSERT(bits->field == cur_field);
|
133 |
|
|
ASSERT(entry_type == NULL);
|
134 |
|
|
if (bits->opcode->is_boolean)
|
135 |
|
|
lf_printf(file, "%d", bits->opcode->boolean_constant);
|
136 |
|
|
else if (bits->opcode->last < bits->field->last)
|
137 |
|
|
lf_printf(file, "%d",
|
138 |
|
|
bits->value << (bits->field->last - bits->opcode->last));
|
139 |
|
|
else
|
140 |
|
|
lf_printf(file, "%d", bits->value);
|
141 |
|
|
}
|
142 |
|
|
else if (bits != NULL
|
143 |
|
|
&& original_name != NULL
|
144 |
|
|
&& strncmp(entry_name,
|
145 |
|
|
original_name, strlen(original_name)) == 0
|
146 |
|
|
&& strncmp(entry_name + strlen(original_name),
|
147 |
|
|
"_is_", strlen("_is_")) == 0
|
148 |
|
|
&& ((bits->opcode->is_boolean
|
149 |
|
|
&& (atol(entry_name + strlen(original_name) + strlen("_is_"))
|
150 |
|
|
== bits->opcode->boolean_constant))
|
151 |
|
|
|| (!bits->opcode->is_boolean))) {
|
152 |
|
|
expression = "constant compare";
|
153 |
|
|
/* An entry, derived from ORIGINAL_NAME, is testing to see of the
|
154 |
|
|
ORIGINAL_NAME has a specific constant value. That value
|
155 |
|
|
matching a boolean or constant field */
|
156 |
|
|
if (bits->opcode->is_boolean)
|
157 |
|
|
lf_printf(file, "%d /* %s == %d */",
|
158 |
|
|
bits->value == 0,
|
159 |
|
|
original_name,
|
160 |
|
|
bits->opcode->boolean_constant);
|
161 |
|
|
else if (bits->opcode->last < bits->field->last)
|
162 |
|
|
lf_printf(file, "%d /* %s == %d */",
|
163 |
|
|
(atol(entry_name + strlen(original_name) + strlen("_is_"))
|
164 |
|
|
== (bits->value << (bits->field->last - bits->opcode->last))),
|
165 |
|
|
original_name,
|
166 |
|
|
(bits->value << (bits->field->last - bits->opcode->last)));
|
167 |
|
|
else
|
168 |
|
|
lf_printf(file, "%d /* %s == %d */",
|
169 |
|
|
(atol(entry_name + strlen(original_name) + strlen("_is_"))
|
170 |
|
|
== bits->value),
|
171 |
|
|
original_name,
|
172 |
|
|
bits->value);
|
173 |
|
|
}
|
174 |
|
|
else {
|
175 |
|
|
/* put the field in the local variable, possibly also enter it
|
176 |
|
|
into the cache */
|
177 |
|
|
expression = "extraction";
|
178 |
|
|
/* handle the cache */
|
179 |
|
|
if ((what_to_do & get_values_from_icache)
|
180 |
|
|
|| (what_to_do & put_values_in_icache)) {
|
181 |
|
|
lf_printf(file, "cache_entry->crack.%s.%s",
|
182 |
|
|
instruction->file_entry->fields[insn_form],
|
183 |
|
|
entry_name);
|
184 |
|
|
if (what_to_do & put_values_in_icache) /* also put it in the cache? */
|
185 |
|
|
lf_printf(file, " = ");
|
186 |
|
|
}
|
187 |
|
|
if ((what_to_do & put_values_in_icache)
|
188 |
|
|
|| what_to_do == do_not_use_icache) {
|
189 |
|
|
if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
|
190 |
|
|
lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
|
191 |
|
|
i2target(hi_bit_nr, cur_field->first),
|
192 |
|
|
i2target(hi_bit_nr, cur_field->last));
|
193 |
|
|
else if (entry_expression != NULL)
|
194 |
|
|
lf_printf(file, "%s", entry_expression);
|
195 |
|
|
else
|
196 |
|
|
lf_printf(file, "eval_%s", entry_name);
|
197 |
|
|
}
|
198 |
|
|
}
|
199 |
|
|
|
200 |
|
|
if (!((what_to_declare == define_variables)
|
201 |
|
|
|| (what_to_declare == undef_variables)))
|
202 |
|
|
lf_printf(file, ";");
|
203 |
|
|
if (reason != NULL)
|
204 |
|
|
lf_printf(file, " /* %s - %s */", reason, expression);
|
205 |
|
|
lf_printf(file, "\n");
|
206 |
|
|
}
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
void
|
210 |
|
|
print_icache_body(lf *file,
|
211 |
|
|
insn *instruction,
|
212 |
|
|
insn_bits *expanded_bits,
|
213 |
|
|
cache_table *cache_rules,
|
214 |
|
|
icache_decl_type what_to_declare,
|
215 |
|
|
icache_body_type what_to_do)
|
216 |
|
|
{
|
217 |
|
|
insn_field *cur_field;
|
218 |
|
|
|
219 |
|
|
/* extract instruction fields */
|
220 |
|
|
lf_printf(file, "/* extraction: %s ",
|
221 |
|
|
instruction->file_entry->fields[insn_format]);
|
222 |
|
|
switch (what_to_declare) {
|
223 |
|
|
case define_variables:
|
224 |
|
|
lf_printf(file, "#define");
|
225 |
|
|
break;
|
226 |
|
|
case declare_variables:
|
227 |
|
|
lf_printf(file, "declare");
|
228 |
|
|
break;
|
229 |
|
|
case undef_variables:
|
230 |
|
|
lf_printf(file, "#undef");
|
231 |
|
|
break;
|
232 |
|
|
}
|
233 |
|
|
lf_printf(file, " ");
|
234 |
|
|
switch (what_to_do) {
|
235 |
|
|
case get_values_from_icache:
|
236 |
|
|
lf_printf(file, "get-values-from-icache");
|
237 |
|
|
break;
|
238 |
|
|
case put_values_in_icache:
|
239 |
|
|
lf_printf(file, "put-values-in-icache");
|
240 |
|
|
break;
|
241 |
|
|
case both_values_and_icache:
|
242 |
|
|
lf_printf(file, "get-values-from-icache|put-values-in-icache");
|
243 |
|
|
break;
|
244 |
|
|
case do_not_use_icache:
|
245 |
|
|
lf_printf(file, "do-not-use-icache");
|
246 |
|
|
break;
|
247 |
|
|
}
|
248 |
|
|
lf_printf(file, " */\n");
|
249 |
|
|
|
250 |
|
|
for (cur_field = instruction->fields->first;
|
251 |
|
|
cur_field->first < insn_bit_size;
|
252 |
|
|
cur_field = cur_field->next) {
|
253 |
|
|
if (cur_field->is_string) {
|
254 |
|
|
insn_bits *bits;
|
255 |
|
|
int found_rule = 0;
|
256 |
|
|
/* find any corresponding value */
|
257 |
|
|
for (bits = expanded_bits;
|
258 |
|
|
bits != NULL;
|
259 |
|
|
bits = bits->last) {
|
260 |
|
|
if (bits->field == cur_field)
|
261 |
|
|
break;
|
262 |
|
|
}
|
263 |
|
|
/* try the cache rule table for what to do */
|
264 |
|
|
{
|
265 |
|
|
cache_table *cache_rule;
|
266 |
|
|
for (cache_rule = cache_rules;
|
267 |
|
|
cache_rule != NULL;
|
268 |
|
|
cache_rule = cache_rule->next) {
|
269 |
|
|
if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
|
270 |
|
|
found_rule = 1;
|
271 |
|
|
if (cache_rule->type == scratch_value
|
272 |
|
|
&& ((what_to_do & put_values_in_icache)
|
273 |
|
|
|| what_to_do == do_not_use_icache))
|
274 |
|
|
print_icache_extraction(file,
|
275 |
|
|
instruction,
|
276 |
|
|
cache_rule->derived_name,
|
277 |
|
|
cache_rule->type_def,
|
278 |
|
|
cache_rule->expression,
|
279 |
|
|
cache_rule->field_name,
|
280 |
|
|
cache_rule->file_entry->file_name,
|
281 |
|
|
cache_rule->file_entry->line_nr,
|
282 |
|
|
cur_field,
|
283 |
|
|
bits,
|
284 |
|
|
what_to_declare,
|
285 |
|
|
do_not_use_icache,
|
286 |
|
|
"icache scratch");
|
287 |
|
|
else if (cache_rule->type == compute_value
|
288 |
|
|
&& ((what_to_do & get_values_from_icache)
|
289 |
|
|
|| what_to_do == do_not_use_icache))
|
290 |
|
|
print_icache_extraction(file,
|
291 |
|
|
instruction,
|
292 |
|
|
cache_rule->derived_name,
|
293 |
|
|
cache_rule->type_def,
|
294 |
|
|
cache_rule->expression,
|
295 |
|
|
cache_rule->field_name,
|
296 |
|
|
cache_rule->file_entry->file_name,
|
297 |
|
|
cache_rule->file_entry->line_nr,
|
298 |
|
|
cur_field,
|
299 |
|
|
bits,
|
300 |
|
|
what_to_declare,
|
301 |
|
|
do_not_use_icache,
|
302 |
|
|
"semantic compute");
|
303 |
|
|
else if (cache_rule->type == cache_value
|
304 |
|
|
&& ((what_to_declare != undef_variables)
|
305 |
|
|
|| !(what_to_do & put_values_in_icache)))
|
306 |
|
|
print_icache_extraction(file,
|
307 |
|
|
instruction,
|
308 |
|
|
cache_rule->derived_name,
|
309 |
|
|
cache_rule->type_def,
|
310 |
|
|
cache_rule->expression,
|
311 |
|
|
cache_rule->field_name,
|
312 |
|
|
cache_rule->file_entry->file_name,
|
313 |
|
|
cache_rule->file_entry->line_nr,
|
314 |
|
|
cur_field,
|
315 |
|
|
bits,
|
316 |
|
|
((what_to_do & put_values_in_icache)
|
317 |
|
|
? declare_variables
|
318 |
|
|
: what_to_declare),
|
319 |
|
|
what_to_do,
|
320 |
|
|
"in icache");
|
321 |
|
|
}
|
322 |
|
|
}
|
323 |
|
|
}
|
324 |
|
|
/* No rule at all, assume that this is needed in the semantic
|
325 |
|
|
function (when values are extracted from the icache) and
|
326 |
|
|
hence must be put into the cache */
|
327 |
|
|
if (found_rule == 0
|
328 |
|
|
&& ((what_to_declare != undef_variables)
|
329 |
|
|
|| !(what_to_do & put_values_in_icache)))
|
330 |
|
|
print_icache_extraction(file,
|
331 |
|
|
instruction,
|
332 |
|
|
cur_field->val_string,
|
333 |
|
|
NULL, NULL, NULL, /* type, exp, orig */
|
334 |
|
|
instruction->file_entry->file_name,
|
335 |
|
|
instruction->file_entry->line_nr,
|
336 |
|
|
cur_field,
|
337 |
|
|
bits,
|
338 |
|
|
((what_to_do & put_values_in_icache)
|
339 |
|
|
? declare_variables
|
340 |
|
|
: what_to_declare),
|
341 |
|
|
what_to_do,
|
342 |
|
|
"default in icache");
|
343 |
|
|
/* any thing else ... */
|
344 |
|
|
}
|
345 |
|
|
}
|
346 |
|
|
|
347 |
|
|
lf_print__internal_reference(file);
|
348 |
|
|
|
349 |
|
|
if ((code & generate_with_insn_in_icache)) {
|
350 |
|
|
lf_printf(file, "\n");
|
351 |
|
|
print_icache_extraction(file,
|
352 |
|
|
instruction,
|
353 |
|
|
"insn",
|
354 |
|
|
"instruction_word",
|
355 |
|
|
"instruction",
|
356 |
|
|
NULL, /* origin */
|
357 |
|
|
NULL, 0, /* file_name & line_nr */
|
358 |
|
|
NULL, NULL,
|
359 |
|
|
what_to_declare,
|
360 |
|
|
what_to_do,
|
361 |
|
|
NULL);
|
362 |
|
|
}
|
363 |
|
|
}
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
|
367 |
|
|
typedef struct _icache_tree icache_tree;
|
368 |
|
|
struct _icache_tree {
|
369 |
|
|
char *name;
|
370 |
|
|
icache_tree *next;
|
371 |
|
|
icache_tree *children;
|
372 |
|
|
};
|
373 |
|
|
|
374 |
|
|
static icache_tree *
|
375 |
|
|
icache_tree_insert(icache_tree *tree,
|
376 |
|
|
char *name)
|
377 |
|
|
{
|
378 |
|
|
icache_tree *new_tree;
|
379 |
|
|
/* find it */
|
380 |
|
|
icache_tree **ptr_to_cur_tree = &tree->children;
|
381 |
|
|
icache_tree *cur_tree = *ptr_to_cur_tree;
|
382 |
|
|
while (cur_tree != NULL
|
383 |
|
|
&& strcmp(cur_tree->name, name) < 0) {
|
384 |
|
|
ptr_to_cur_tree = &cur_tree->next;
|
385 |
|
|
cur_tree = *ptr_to_cur_tree;
|
386 |
|
|
}
|
387 |
|
|
ASSERT(cur_tree == NULL
|
388 |
|
|
|| strcmp(cur_tree->name, name) >= 0);
|
389 |
|
|
/* already in the tree */
|
390 |
|
|
if (cur_tree != NULL
|
391 |
|
|
&& strcmp(cur_tree->name, name) == 0)
|
392 |
|
|
return cur_tree;
|
393 |
|
|
/* missing, insert it */
|
394 |
|
|
ASSERT(cur_tree == NULL
|
395 |
|
|
|| strcmp(cur_tree->name, name) > 0);
|
396 |
|
|
new_tree = ZALLOC(icache_tree);
|
397 |
|
|
new_tree->name = name;
|
398 |
|
|
new_tree->next = cur_tree;
|
399 |
|
|
*ptr_to_cur_tree = new_tree;
|
400 |
|
|
return new_tree;
|
401 |
|
|
}
|
402 |
|
|
|
403 |
|
|
|
404 |
|
|
static icache_tree *
|
405 |
|
|
insn_table_cache_fields(insn_table *table)
|
406 |
|
|
{
|
407 |
|
|
icache_tree *tree = ZALLOC(icache_tree);
|
408 |
|
|
insn *instruction;
|
409 |
|
|
for (instruction = table->insns;
|
410 |
|
|
instruction != NULL;
|
411 |
|
|
instruction = instruction->next) {
|
412 |
|
|
insn_field *field;
|
413 |
|
|
icache_tree *form =
|
414 |
|
|
icache_tree_insert(tree,
|
415 |
|
|
instruction->file_entry->fields[insn_form]);
|
416 |
|
|
for (field = instruction->fields->first;
|
417 |
|
|
field != NULL;
|
418 |
|
|
field = field->next) {
|
419 |
|
|
if (field->is_string)
|
420 |
|
|
icache_tree_insert(form, field->val_string);
|
421 |
|
|
}
|
422 |
|
|
}
|
423 |
|
|
return tree;
|
424 |
|
|
}
|
425 |
|
|
|
426 |
|
|
|
427 |
|
|
|
428 |
|
|
extern void
|
429 |
|
|
print_icache_struct(insn_table *instructions,
|
430 |
|
|
cache_table *cache_rules,
|
431 |
|
|
lf *file)
|
432 |
|
|
{
|
433 |
|
|
icache_tree *tree = insn_table_cache_fields(instructions);
|
434 |
|
|
|
435 |
|
|
lf_printf(file, "\n");
|
436 |
|
|
lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
|
437 |
|
|
(code & generate_with_icache) ? icache_size : 0);
|
438 |
|
|
lf_printf(file, "\n");
|
439 |
|
|
|
440 |
|
|
/* create an instruction cache if being used */
|
441 |
|
|
if ((code & generate_with_icache)) {
|
442 |
|
|
icache_tree *form;
|
443 |
|
|
lf_printf(file, "typedef struct _idecode_cache {\n");
|
444 |
|
|
lf_printf(file, " unsigned_word address;\n");
|
445 |
|
|
lf_printf(file, " void *semantic;\n");
|
446 |
|
|
lf_printf(file, " union {\n");
|
447 |
|
|
for (form = tree->children;
|
448 |
|
|
form != NULL;
|
449 |
|
|
form = form->next) {
|
450 |
|
|
icache_tree *field;
|
451 |
|
|
lf_printf(file, " struct {\n");
|
452 |
|
|
if (code & generate_with_insn_in_icache)
|
453 |
|
|
lf_printf(file, " instruction_word insn;\n");
|
454 |
|
|
for (field = form->children;
|
455 |
|
|
field != NULL;
|
456 |
|
|
field = field->next) {
|
457 |
|
|
cache_table *cache_rule;
|
458 |
|
|
int found_rule = 0;
|
459 |
|
|
for (cache_rule = cache_rules;
|
460 |
|
|
cache_rule != NULL;
|
461 |
|
|
cache_rule = cache_rule->next) {
|
462 |
|
|
if (strcmp(field->name, cache_rule->field_name) == 0) {
|
463 |
|
|
found_rule = 1;
|
464 |
|
|
if (cache_rule->derived_name != NULL)
|
465 |
|
|
lf_printf(file, " %s %s; /* %s */\n",
|
466 |
|
|
(cache_rule->type_def == NULL
|
467 |
|
|
? "unsigned"
|
468 |
|
|
: cache_rule->type_def),
|
469 |
|
|
cache_rule->derived_name,
|
470 |
|
|
cache_rule->field_name);
|
471 |
|
|
}
|
472 |
|
|
}
|
473 |
|
|
if (!found_rule)
|
474 |
|
|
lf_printf(file, " unsigned %s;\n", field->name);
|
475 |
|
|
}
|
476 |
|
|
lf_printf(file, " } %s;\n", form->name);
|
477 |
|
|
}
|
478 |
|
|
lf_printf(file, " } crack;\n");
|
479 |
|
|
lf_printf(file, "} idecode_cache;\n");
|
480 |
|
|
}
|
481 |
|
|
else {
|
482 |
|
|
/* alernativly, since no cache, emit a dummy definition for
|
483 |
|
|
idecode_cache so that code refering to the type can still compile */
|
484 |
|
|
lf_printf(file, "typedef void idecode_cache;\n");
|
485 |
|
|
}
|
486 |
|
|
lf_printf(file, "\n");
|
487 |
|
|
}
|
488 |
|
|
|
489 |
|
|
|
490 |
|
|
|
491 |
|
|
static void
|
492 |
|
|
print_icache_function(lf *file,
|
493 |
|
|
insn *instruction,
|
494 |
|
|
insn_bits *expanded_bits,
|
495 |
|
|
opcode_field *opcodes,
|
496 |
|
|
cache_table *cache_rules)
|
497 |
|
|
{
|
498 |
|
|
int indent;
|
499 |
|
|
|
500 |
|
|
/* generate code to enter decoded instruction into the icache */
|
501 |
|
|
lf_printf(file, "\n");
|
502 |
|
|
lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
|
503 |
|
|
indent = print_function_name(file,
|
504 |
|
|
instruction->file_entry->fields[insn_name],
|
505 |
|
|
expanded_bits,
|
506 |
|
|
function_name_prefix_icache);
|
507 |
|
|
lf_indent(file, +indent);
|
508 |
|
|
lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
|
509 |
|
|
lf_indent(file, -indent);
|
510 |
|
|
|
511 |
|
|
/* function header */
|
512 |
|
|
lf_printf(file, "{\n");
|
513 |
|
|
lf_indent(file, +2);
|
514 |
|
|
|
515 |
|
|
print_my_defines(file, expanded_bits, instruction->file_entry);
|
516 |
|
|
print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
|
517 |
|
|
|
518 |
|
|
print_idecode_validate(file, instruction, opcodes);
|
519 |
|
|
|
520 |
|
|
lf_printf(file, "\n");
|
521 |
|
|
lf_printf(file, "{\n");
|
522 |
|
|
lf_indent(file, +2);
|
523 |
|
|
if ((code & generate_with_semantic_icache))
|
524 |
|
|
lf_printf(file, "unsigned_word nia;\n");
|
525 |
|
|
print_icache_body(file,
|
526 |
|
|
instruction,
|
527 |
|
|
expanded_bits,
|
528 |
|
|
cache_rules,
|
529 |
|
|
((code & generate_with_direct_access)
|
530 |
|
|
? define_variables
|
531 |
|
|
: declare_variables),
|
532 |
|
|
((code & generate_with_semantic_icache)
|
533 |
|
|
? both_values_and_icache
|
534 |
|
|
: put_values_in_icache));
|
535 |
|
|
|
536 |
|
|
lf_printf(file, "\n");
|
537 |
|
|
lf_printf(file, "cache_entry->address = cia;\n");
|
538 |
|
|
lf_printf(file, "cache_entry->semantic = ");
|
539 |
|
|
print_function_name(file,
|
540 |
|
|
instruction->file_entry->fields[insn_name],
|
541 |
|
|
expanded_bits,
|
542 |
|
|
function_name_prefix_semantics);
|
543 |
|
|
lf_printf(file, ";\n");
|
544 |
|
|
lf_printf(file, "\n");
|
545 |
|
|
|
546 |
|
|
if ((code & generate_with_semantic_icache)) {
|
547 |
|
|
lf_printf(file, "/* semantic routine */\n");
|
548 |
|
|
print_semantic_body(file,
|
549 |
|
|
instruction,
|
550 |
|
|
expanded_bits,
|
551 |
|
|
opcodes);
|
552 |
|
|
lf_printf(file, "return nia;\n");
|
553 |
|
|
}
|
554 |
|
|
|
555 |
|
|
if (!(code & generate_with_semantic_icache)) {
|
556 |
|
|
lf_printf(file, "/* return the function proper */\n");
|
557 |
|
|
lf_printf(file, "return ");
|
558 |
|
|
print_function_name(file,
|
559 |
|
|
instruction->file_entry->fields[insn_name],
|
560 |
|
|
expanded_bits,
|
561 |
|
|
function_name_prefix_semantics);
|
562 |
|
|
lf_printf(file, ";\n");
|
563 |
|
|
}
|
564 |
|
|
|
565 |
|
|
if ((code & generate_with_direct_access))
|
566 |
|
|
print_icache_body(file,
|
567 |
|
|
instruction,
|
568 |
|
|
expanded_bits,
|
569 |
|
|
cache_rules,
|
570 |
|
|
undef_variables,
|
571 |
|
|
((code & generate_with_semantic_icache)
|
572 |
|
|
? both_values_and_icache
|
573 |
|
|
: put_values_in_icache));
|
574 |
|
|
|
575 |
|
|
lf_indent(file, -2);
|
576 |
|
|
lf_printf(file, "}\n");
|
577 |
|
|
lf_indent(file, -2);
|
578 |
|
|
lf_printf(file, "}\n");
|
579 |
|
|
}
|
580 |
|
|
|
581 |
|
|
|
582 |
|
|
void
|
583 |
|
|
print_icache_definition(insn_table *entry,
|
584 |
|
|
lf *file,
|
585 |
|
|
void *data,
|
586 |
|
|
insn *instruction,
|
587 |
|
|
int depth)
|
588 |
|
|
{
|
589 |
|
|
cache_table *cache_rules = (cache_table*)data;
|
590 |
|
|
if (generate_expanded_instructions) {
|
591 |
|
|
ASSERT(entry->nr_insn == 1
|
592 |
|
|
&& entry->opcode == NULL
|
593 |
|
|
&& entry->parent != NULL
|
594 |
|
|
&& entry->parent->opcode != NULL);
|
595 |
|
|
ASSERT(entry->nr_insn == 1
|
596 |
|
|
&& entry->opcode == NULL
|
597 |
|
|
&& entry->parent != NULL
|
598 |
|
|
&& entry->parent->opcode != NULL
|
599 |
|
|
&& entry->parent->opcode_rule != NULL);
|
600 |
|
|
print_icache_function(file,
|
601 |
|
|
entry->insns,
|
602 |
|
|
entry->expanded_bits,
|
603 |
|
|
entry->opcode,
|
604 |
|
|
cache_rules);
|
605 |
|
|
}
|
606 |
|
|
else {
|
607 |
|
|
print_icache_function(file,
|
608 |
|
|
instruction,
|
609 |
|
|
NULL,
|
610 |
|
|
NULL,
|
611 |
|
|
cache_rules);
|
612 |
|
|
}
|
613 |
|
|
}
|
614 |
|
|
|
615 |
|
|
|
616 |
|
|
|
617 |
|
|
void
|
618 |
|
|
print_icache_internal_function_declaration(insn_table *table,
|
619 |
|
|
lf *file,
|
620 |
|
|
void *data,
|
621 |
|
|
table_entry *function)
|
622 |
|
|
{
|
623 |
|
|
ASSERT((code & generate_with_icache) != 0);
|
624 |
|
|
if (it_is("internal", function->fields[insn_flags])) {
|
625 |
|
|
lf_printf(file, "\n");
|
626 |
|
|
lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
|
627 |
|
|
"\n");
|
628 |
|
|
print_function_name(file,
|
629 |
|
|
function->fields[insn_name],
|
630 |
|
|
NULL,
|
631 |
|
|
function_name_prefix_icache);
|
632 |
|
|
lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
|
633 |
|
|
}
|
634 |
|
|
}
|
635 |
|
|
|
636 |
|
|
|
637 |
|
|
void
|
638 |
|
|
print_icache_internal_function_definition(insn_table *table,
|
639 |
|
|
lf *file,
|
640 |
|
|
void *data,
|
641 |
|
|
table_entry *function)
|
642 |
|
|
{
|
643 |
|
|
ASSERT((code & generate_with_icache) != 0);
|
644 |
|
|
if (it_is("internal", function->fields[insn_flags])) {
|
645 |
|
|
lf_printf(file, "\n");
|
646 |
|
|
lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
|
647 |
|
|
"\n");
|
648 |
|
|
print_function_name(file,
|
649 |
|
|
function->fields[insn_name],
|
650 |
|
|
NULL,
|
651 |
|
|
function_name_prefix_icache);
|
652 |
|
|
lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
|
653 |
|
|
lf_printf(file, "{\n");
|
654 |
|
|
lf_indent(file, +2);
|
655 |
|
|
lf_printf(file, "/* semantic routine */\n");
|
656 |
|
|
table_entry_print_cpp_line_nr(file, function);
|
657 |
|
|
if ((code & generate_with_semantic_icache)) {
|
658 |
|
|
lf_print__c_code(file, function->annex);
|
659 |
|
|
lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
|
660 |
|
|
lf_printf(file, "return 0;\n");
|
661 |
|
|
}
|
662 |
|
|
else {
|
663 |
|
|
lf_printf(file, "return ");
|
664 |
|
|
print_function_name(file,
|
665 |
|
|
function->fields[insn_name],
|
666 |
|
|
NULL,
|
667 |
|
|
function_name_prefix_semantics);
|
668 |
|
|
lf_printf(file, ";\n");
|
669 |
|
|
}
|
670 |
|
|
|
671 |
|
|
lf_print__internal_reference(file);
|
672 |
|
|
lf_indent(file, -2);
|
673 |
|
|
lf_printf(file, "}\n");
|
674 |
|
|
}
|
675 |
|
|
}
|