gen.c revision 1.1 1 1.1 christos /* The IGEN simulator generator for GDB, the GNU Debugger.
2 1.1 christos
3 1.1 christos Copyright 2002-2014 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos Contributed by Andrew Cagney.
6 1.1 christos
7 1.1 christos This file is part of GDB.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 1.1 christos
22 1.1 christos
23 1.1 christos #include "misc.h"
24 1.1 christos #include "lf.h"
25 1.1 christos #include "table.h"
26 1.1 christos #include "filter.h"
27 1.1 christos
28 1.1 christos #include "igen.h"
29 1.1 christos #include "ld-insn.h"
30 1.1 christos #include "ld-decode.h"
31 1.1 christos #include "gen.h"
32 1.1 christos
33 1.1 christos static insn_uint
34 1.1 christos sub_val (insn_uint val, int val_last_pos, int first_pos, int last_pos)
35 1.1 christos {
36 1.1 christos return ((val >> (val_last_pos - last_pos))
37 1.1 christos & (((insn_uint) 1 << (last_pos - first_pos + 1)) - 1));
38 1.1 christos }
39 1.1 christos
40 1.1 christos static void
41 1.1 christos update_depth (lf *file, gen_entry *entry, int depth, void *data)
42 1.1 christos {
43 1.1 christos int *max_depth = (int *) data;
44 1.1 christos if (*max_depth < depth)
45 1.1 christos *max_depth = depth;
46 1.1 christos }
47 1.1 christos
48 1.1 christos
49 1.1 christos int
50 1.1 christos gen_entry_depth (gen_entry *table)
51 1.1 christos {
52 1.1 christos int depth = 0;
53 1.1 christos gen_entry_traverse_tree (NULL, table, 1, NULL, /*start */
54 1.1 christos update_depth, NULL, /*end */
55 1.1 christos &depth); /* data */
56 1.1 christos return depth;
57 1.1 christos }
58 1.1 christos
59 1.1 christos
60 1.1 christos static void
61 1.1 christos print_gen_entry_path (line_ref *line, gen_entry *table, error_func *print)
62 1.1 christos {
63 1.1 christos if (table->parent == NULL)
64 1.1 christos {
65 1.1 christos if (table->top->model != NULL)
66 1.1 christos print (line, "%s", table->top->model->name);
67 1.1 christos else
68 1.1 christos print (line, "");
69 1.1 christos }
70 1.1 christos else
71 1.1 christos {
72 1.1 christos print_gen_entry_path (line, table->parent, print);
73 1.1 christos print (NULL, ".%d", table->opcode_nr);
74 1.1 christos }
75 1.1 christos }
76 1.1 christos
77 1.1 christos static void
78 1.1 christos print_gen_entry_insns (gen_entry *table,
79 1.1 christos error_func *print,
80 1.1 christos char *first_message, char *next_message)
81 1.1 christos {
82 1.1 christos insn_list *i;
83 1.1 christos char *message;
84 1.1 christos message = first_message;
85 1.1 christos for (i = table->insns; i != NULL; i = i->next)
86 1.1 christos {
87 1.1 christos insn_entry *insn = i->insn;
88 1.1 christos print_gen_entry_path (insn->line, table, print);
89 1.1 christos print (NULL, ": %s.%s %s\n", insn->format_name, insn->name, message);
90 1.1 christos if (next_message != NULL)
91 1.1 christos message = next_message;
92 1.1 christos }
93 1.1 christos }
94 1.1 christos
95 1.1 christos /* same as strcmp */
96 1.1 christos static int
97 1.1 christos insn_field_cmp (insn_word_entry *l, insn_word_entry *r)
98 1.1 christos {
99 1.1 christos while (1)
100 1.1 christos {
101 1.1 christos int bit_nr;
102 1.1 christos if (l == NULL && r == NULL)
103 1.1 christos return 0; /* all previous fields the same */
104 1.1 christos if (l == NULL)
105 1.1 christos return -1; /* left shorter than right */
106 1.1 christos if (r == NULL)
107 1.1 christos return +1; /* left longer than right */
108 1.1 christos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
109 1.1 christos {
110 1.1 christos if (l->bit[bit_nr]->field->type != insn_field_string)
111 1.1 christos continue;
112 1.1 christos if (r->bit[bit_nr]->field->type != insn_field_string)
113 1.1 christos continue;
114 1.1 christos if (l->bit[bit_nr]->field->conditions == NULL)
115 1.1 christos continue;
116 1.1 christos if (r->bit[bit_nr]->field->conditions == NULL)
117 1.1 christos continue;
118 1.1 christos if (0)
119 1.1 christos printf ("%s%s%s VS %s%s%s\n",
120 1.1 christos l->bit[bit_nr]->field->val_string,
121 1.1 christos l->bit[bit_nr]->field->conditions->test ==
122 1.1 christos insn_field_cond_eq ? "=" : "!",
123 1.1 christos l->bit[bit_nr]->field->conditions->string,
124 1.1 christos r->bit[bit_nr]->field->val_string,
125 1.1 christos r->bit[bit_nr]->field->conditions->test ==
126 1.1 christos insn_field_cond_eq ? "=" : "!",
127 1.1 christos r->bit[bit_nr]->field->conditions->string);
128 1.1 christos if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq
129 1.1 christos && r->bit[bit_nr]->field->conditions->test ==
130 1.1 christos insn_field_cond_eq)
131 1.1 christos {
132 1.1 christos if (l->bit[bit_nr]->field->conditions->type ==
133 1.1 christos insn_field_cond_field
134 1.1 christos && r->bit[bit_nr]->field->conditions->type ==
135 1.1 christos insn_field_cond_field)
136 1.1 christos /* somewhat arbitrary */
137 1.1 christos {
138 1.1 christos int cmp = strcmp (l->bit[bit_nr]->field->conditions->string,
139 1.1 christos r->bit[bit_nr]->field->conditions->
140 1.1 christos string);
141 1.1 christos if (cmp != 0)
142 1.1 christos return cmp;
143 1.1 christos else
144 1.1 christos continue;
145 1.1 christos }
146 1.1 christos if (l->bit[bit_nr]->field->conditions->type ==
147 1.1 christos insn_field_cond_field)
148 1.1 christos return +1;
149 1.1 christos if (r->bit[bit_nr]->field->conditions->type ==
150 1.1 christos insn_field_cond_field)
151 1.1 christos return -1;
152 1.1 christos /* The case of both fields having constant values should have
153 1.1 christos already have been handled because such fields are converted
154 1.1 christos into normal constant fields, but we must not make this
155 1.1 christos an assert, as we wouldn't gracefully handle an (invalid)
156 1.1 christos duplicate insn description. */
157 1.1 christos continue;
158 1.1 christos }
159 1.1 christos if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
160 1.1 christos return +1; /* left = only */
161 1.1 christos if (r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)
162 1.1 christos return -1; /* right = only */
163 1.1 christos /* FIXME: Need to some what arbitrarily order conditional lists */
164 1.1 christos continue;
165 1.1 christos }
166 1.1 christos l = l->next;
167 1.1 christos r = r->next;
168 1.1 christos }
169 1.1 christos }
170 1.1 christos
171 1.1 christos /* same as strcmp */
172 1.1 christos static int
173 1.1 christos insn_word_cmp (insn_word_entry *l, insn_word_entry *r)
174 1.1 christos {
175 1.1 christos while (1)
176 1.1 christos {
177 1.1 christos int bit_nr;
178 1.1 christos if (l == NULL && r == NULL)
179 1.1 christos return 0; /* all previous fields the same */
180 1.1 christos if (l == NULL)
181 1.1 christos return -1; /* left shorter than right */
182 1.1 christos if (r == NULL)
183 1.1 christos return +1; /* left longer than right */
184 1.1 christos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
185 1.1 christos {
186 1.1 christos if (l->bit[bit_nr]->mask < r->bit[bit_nr]->mask)
187 1.1 christos return -1;
188 1.1 christos if (l->bit[bit_nr]->mask > r->bit[bit_nr]->mask)
189 1.1 christos return 1;
190 1.1 christos if (l->bit[bit_nr]->value < r->bit[bit_nr]->value)
191 1.1 christos return -1;
192 1.1 christos if (l->bit[bit_nr]->value > r->bit[bit_nr]->value)
193 1.1 christos return 1;
194 1.1 christos }
195 1.1 christos l = l->next;
196 1.1 christos r = r->next;
197 1.1 christos }
198 1.1 christos }
199 1.1 christos
200 1.1 christos /* same as strcmp */
201 1.1 christos static int
202 1.1 christos opcode_bit_cmp (opcode_bits *l, opcode_bits *r)
203 1.1 christos {
204 1.1 christos if (l == NULL && r == NULL)
205 1.1 christos return 0; /* all previous bits the same */
206 1.1 christos if (l == NULL)
207 1.1 christos return -1; /* left shorter than right */
208 1.1 christos if (r == NULL)
209 1.1 christos return +1; /* left longer than right */
210 1.1 christos /* most significant word */
211 1.1 christos if (l->field->word_nr < r->field->word_nr)
212 1.1 christos return +1; /* left has more significant word */
213 1.1 christos if (l->field->word_nr > r->field->word_nr)
214 1.1 christos return -1; /* right has more significant word */
215 1.1 christos /* most significant bit? */
216 1.1 christos if (l->first < r->first)
217 1.1 christos return +1; /* left as more significant bit */
218 1.1 christos if (l->first > r->first)
219 1.1 christos return -1; /* right as more significant bit */
220 1.1 christos /* nr bits? */
221 1.1 christos if (l->last < r->last)
222 1.1 christos return +1; /* left as less bits */
223 1.1 christos if (l->last > r->last)
224 1.1 christos return -1; /* right as less bits */
225 1.1 christos /* value? */
226 1.1 christos if (l->value < r->value)
227 1.1 christos return -1;
228 1.1 christos if (l->value > r->value)
229 1.1 christos return 1;
230 1.1 christos return 0;
231 1.1 christos }
232 1.1 christos
233 1.1 christos
234 1.1 christos /* same as strcmp */
235 1.1 christos static int
236 1.1 christos opcode_bits_cmp (opcode_bits *l, opcode_bits *r)
237 1.1 christos {
238 1.1 christos while (1)
239 1.1 christos {
240 1.1 christos int cmp;
241 1.1 christos if (l == NULL && r == NULL)
242 1.1 christos return 0; /* all previous bits the same */
243 1.1 christos cmp = opcode_bit_cmp (l, r);
244 1.1 christos if (cmp != 0)
245 1.1 christos return cmp;
246 1.1 christos l = l->next;
247 1.1 christos r = r->next;
248 1.1 christos }
249 1.1 christos }
250 1.1 christos
251 1.1 christos /* same as strcmp */
252 1.1 christos static opcode_bits *
253 1.1 christos new_opcode_bits (opcode_bits *old_bits,
254 1.1 christos int value,
255 1.1 christos int first,
256 1.1 christos int last, insn_field_entry *field, opcode_field *opcode)
257 1.1 christos {
258 1.1 christos opcode_bits *new_bits = ZALLOC (opcode_bits);
259 1.1 christos new_bits->field = field;
260 1.1 christos new_bits->value = value;
261 1.1 christos new_bits->first = first;
262 1.1 christos new_bits->last = last;
263 1.1 christos new_bits->opcode = opcode;
264 1.1 christos
265 1.1 christos if (old_bits != NULL)
266 1.1 christos {
267 1.1 christos opcode_bits *new_list;
268 1.1 christos opcode_bits **last = &new_list;
269 1.1 christos new_list = new_opcode_bits (old_bits->next,
270 1.1 christos old_bits->value,
271 1.1 christos old_bits->first,
272 1.1 christos old_bits->last,
273 1.1 christos old_bits->field, old_bits->opcode);
274 1.1 christos while (*last != NULL)
275 1.1 christos {
276 1.1 christos int cmp = opcode_bit_cmp (new_bits, *last);
277 1.1 christos if (cmp < 0) /* new < new_list */
278 1.1 christos {
279 1.1 christos break;
280 1.1 christos }
281 1.1 christos if (cmp == 0)
282 1.1 christos {
283 1.1 christos ERROR ("Duplicated insn bits in list");
284 1.1 christos }
285 1.1 christos last = &(*last)->next;
286 1.1 christos }
287 1.1 christos new_bits->next = *last;
288 1.1 christos *last = new_bits;
289 1.1 christos return new_list;
290 1.1 christos }
291 1.1 christos else
292 1.1 christos {
293 1.1 christos return new_bits;
294 1.1 christos }
295 1.1 christos }
296 1.1 christos
297 1.1 christos /* Same as strcmp(). */
298 1.1 christos static int
299 1.1 christos name_cmp (const char *l, const char *r)
300 1.1 christos {
301 1.1 christos if (l == NULL && r == NULL)
302 1.1 christos return 0;
303 1.1 christos if (l != NULL && r == NULL)
304 1.1 christos return -1;
305 1.1 christos if (l == NULL && r != NULL)
306 1.1 christos return +1;
307 1.1 christos return strcmp (l, r);
308 1.1 christos }
309 1.1 christos
310 1.1 christos
311 1.1 christos typedef enum
312 1.1 christos {
313 1.1 christos merge_duplicate_insns,
314 1.1 christos report_duplicate_insns,
315 1.1 christos }
316 1.1 christos duplicate_insn_actions;
317 1.1 christos
318 1.1 christos static insn_list *
319 1.1 christos insn_list_insert (insn_list **cur_insn_ptr,
320 1.1 christos int *nr_insns,
321 1.1 christos insn_entry * insn,
322 1.1 christos opcode_bits *expanded_bits,
323 1.1 christos opcode_field *opcodes,
324 1.1 christos int nr_prefetched_words,
325 1.1 christos duplicate_insn_actions duplicate_action)
326 1.1 christos {
327 1.1 christos /* insert it according to the order of the fields & bits */
328 1.1 christos for (; (*cur_insn_ptr) != NULL; cur_insn_ptr = &(*cur_insn_ptr)->next)
329 1.1 christos {
330 1.1 christos int cmp;
331 1.1 christos
332 1.1 christos /* key#1 sort according to the constant fields of each instruction */
333 1.1 christos cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words);
334 1.1 christos if (cmp < 0)
335 1.1 christos break;
336 1.1 christos else if (cmp > 0)
337 1.1 christos continue;
338 1.1 christos
339 1.1 christos /* key#2 sort according to the expanded bits of each instruction */
340 1.1 christos cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits);
341 1.1 christos if (cmp < 0)
342 1.1 christos break;
343 1.1 christos else if (cmp > 0)
344 1.1 christos continue;
345 1.1 christos
346 1.1 christos /* key#3 sort according to the non-constant fields of each instruction */
347 1.1 christos cmp = insn_field_cmp (insn->words, (*cur_insn_ptr)->insn->words);
348 1.1 christos if (cmp < 0)
349 1.1 christos break;
350 1.1 christos else if (cmp > 0)
351 1.1 christos continue;
352 1.1 christos
353 1.1 christos if (duplicate_action == merge_duplicate_insns)
354 1.1 christos {
355 1.1 christos /* key#4: If we're going to merge duplicates, also sort
356 1.1 christos according to the format_name. Two instructions with
357 1.1 christos identical decode patterns, but different names, are
358 1.1 christos considered different when merging. Duplicates are only
359 1.1 christos important when creating a decode table (implied by
360 1.1 christos report_duplicate_insns) as such a table only has the
361 1.1 christos instruction's bit code as a way of differentiating
362 1.1 christos between instructions. */
363 1.1 christos int cmp = name_cmp (insn->format_name,
364 1.1 christos (*cur_insn_ptr)->insn->format_name);
365 1.1 christos if (cmp < 0)
366 1.1 christos break;
367 1.1 christos else if (cmp > 0)
368 1.1 christos continue;
369 1.1 christos }
370 1.1 christos
371 1.1 christos if (duplicate_action == merge_duplicate_insns)
372 1.1 christos {
373 1.1 christos /* key#5: If we're going to merge duplicates, also sort
374 1.1 christos according to the name. See comment above for
375 1.1 christos format_name. */
376 1.1 christos int cmp = name_cmp (insn->name, (*cur_insn_ptr)->insn->name);
377 1.1 christos if (cmp < 0)
378 1.1 christos break;
379 1.1 christos else if (cmp > 0)
380 1.1 christos continue;
381 1.1 christos }
382 1.1 christos
383 1.1 christos /* duplicate keys, report problem */
384 1.1 christos switch (duplicate_action)
385 1.1 christos {
386 1.1 christos case report_duplicate_insns:
387 1.1 christos /* It would appear that we have two instructions with the
388 1.1 christos same constant field values across all words and bits.
389 1.1 christos This error can also occure when insn_field_cmp() is
390 1.1 christos failing to differentiate between two instructions that
391 1.1 christos differ only in their conditional fields. */
392 1.1 christos warning (insn->line,
393 1.1 christos "Two instructions with identical constant fields\n");
394 1.1 christos error ((*cur_insn_ptr)->insn->line,
395 1.1 christos "Location of duplicate instruction\n");
396 1.1 christos case merge_duplicate_insns:
397 1.1 christos /* Add the opcode path to the instructions list */
398 1.1 christos if (options.trace.insn_insertion)
399 1.1 christos {
400 1.1 christos notify ((*cur_insn_ptr)->insn->line,
401 1.1 christos "%s.%s: insert merge %s.%s\n",
402 1.1 christos (*cur_insn_ptr)->insn->format_name,
403 1.1 christos (*cur_insn_ptr)->insn->name,
404 1.1 christos insn->format_name,
405 1.1 christos insn->name);
406 1.1 christos }
407 1.1 christos if (opcodes != NULL)
408 1.1 christos {
409 1.1 christos insn_opcodes **last = &(*cur_insn_ptr)->opcodes;
410 1.1 christos while (*last != NULL)
411 1.1 christos {
412 1.1 christos last = &(*last)->next;
413 1.1 christos }
414 1.1 christos (*last) = ZALLOC (insn_opcodes);
415 1.1 christos (*last)->opcode = opcodes;
416 1.1 christos }
417 1.1 christos /* Use the larger nr_prefetched_words */
418 1.1 christos if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words)
419 1.1 christos (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words;
420 1.1 christos return (*cur_insn_ptr);
421 1.1 christos }
422 1.1 christos
423 1.1 christos }
424 1.1 christos
425 1.1 christos /* create a new list entry and insert it */
426 1.1 christos {
427 1.1 christos insn_list *new_insn = ZALLOC (insn_list);
428 1.1 christos if (options.trace.insn_insertion)
429 1.1 christos {
430 1.1 christos notify (insn->line,
431 1.1 christos "%s.%s: insert new\n",
432 1.1 christos insn->format_name,
433 1.1 christos insn->name);
434 1.1 christos }
435 1.1 christos new_insn->insn = insn;
436 1.1 christos new_insn->expanded_bits = expanded_bits;
437 1.1 christos new_insn->next = (*cur_insn_ptr);
438 1.1 christos new_insn->nr_prefetched_words = nr_prefetched_words;
439 1.1 christos if (opcodes != NULL)
440 1.1 christos {
441 1.1 christos new_insn->opcodes = ZALLOC (insn_opcodes);
442 1.1 christos new_insn->opcodes->opcode = opcodes;
443 1.1 christos }
444 1.1 christos (*cur_insn_ptr) = new_insn;
445 1.1 christos }
446 1.1 christos
447 1.1 christos *nr_insns += 1;
448 1.1 christos
449 1.1 christos return (*cur_insn_ptr);
450 1.1 christos }
451 1.1 christos
452 1.1 christos
453 1.1 christos extern void
454 1.1 christos gen_entry_traverse_tree (lf *file,
455 1.1 christos gen_entry *table,
456 1.1 christos int depth,
457 1.1 christos gen_entry_handler * start,
458 1.1 christos gen_entry_handler * leaf,
459 1.1 christos gen_entry_handler * end, void *data)
460 1.1 christos {
461 1.1 christos gen_entry *entry;
462 1.1 christos
463 1.1 christos ASSERT (table !=NULL);
464 1.1 christos ASSERT (table->opcode != NULL);
465 1.1 christos ASSERT (table->nr_entries > 0);
466 1.1 christos ASSERT (table->entries != 0);
467 1.1 christos
468 1.1 christos /* prefix */
469 1.1 christos if (start != NULL && depth >= 0)
470 1.1 christos {
471 1.1 christos start (file, table, depth, data);
472 1.1 christos }
473 1.1 christos /* infix leaves */
474 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
475 1.1 christos {
476 1.1 christos if (entry->entries != NULL && depth != 0)
477 1.1 christos {
478 1.1 christos gen_entry_traverse_tree (file, entry, depth + 1,
479 1.1 christos start, leaf, end, data);
480 1.1 christos }
481 1.1 christos else if (depth >= 0)
482 1.1 christos {
483 1.1 christos if (leaf != NULL)
484 1.1 christos {
485 1.1 christos leaf (file, entry, depth, data);
486 1.1 christos }
487 1.1 christos }
488 1.1 christos }
489 1.1 christos /* postfix */
490 1.1 christos if (end != NULL && depth >= 0)
491 1.1 christos {
492 1.1 christos end (file, table, depth, data);
493 1.1 christos }
494 1.1 christos }
495 1.1 christos
496 1.1 christos
497 1.1 christos
498 1.1 christos /* create a list element containing a single gen_table entry */
499 1.1 christos
500 1.1 christos static gen_list *
501 1.1 christos make_table (insn_table *isa, decode_table *rules, model_entry *model)
502 1.1 christos {
503 1.1 christos insn_entry *insn;
504 1.1 christos gen_list *entry = ZALLOC (gen_list);
505 1.1 christos entry->table = ZALLOC (gen_entry);
506 1.1 christos entry->table->top = entry;
507 1.1 christos entry->model = model;
508 1.1 christos entry->isa = isa;
509 1.1 christos for (insn = isa->insns; insn != NULL; insn = insn->next)
510 1.1 christos {
511 1.1 christos if (model == NULL
512 1.1 christos || insn->processors == NULL
513 1.1 christos || filter_is_member (insn->processors, model->name))
514 1.1 christos {
515 1.1 christos insn_list_insert (&entry->table->insns, &entry->table->nr_insns, insn, NULL, /* expanded_bits - none yet */
516 1.1 christos NULL, /* opcodes - none yet */
517 1.1 christos 0, /* nr_prefetched_words - none yet */
518 1.1 christos report_duplicate_insns);
519 1.1 christos }
520 1.1 christos }
521 1.1 christos entry->table->opcode_rule = rules;
522 1.1 christos return entry;
523 1.1 christos }
524 1.1 christos
525 1.1 christos
526 1.1 christos gen_table *
527 1.1 christos make_gen_tables (insn_table *isa, decode_table *rules)
528 1.1 christos {
529 1.1 christos gen_table *gen = ZALLOC (gen_table);
530 1.1 christos gen->isa = isa;
531 1.1 christos gen->rules = rules;
532 1.1 christos if (options.gen.multi_sim)
533 1.1 christos {
534 1.1 christos gen_list **last = &gen->tables;
535 1.1 christos model_entry *model;
536 1.1 christos filter *processors;
537 1.1 christos if (options.model_filter != NULL)
538 1.1 christos processors = options.model_filter;
539 1.1 christos else
540 1.1 christos processors = isa->model->processors;
541 1.1 christos for (model = isa->model->models; model != NULL; model = model->next)
542 1.1 christos {
543 1.1 christos if (filter_is_member (processors, model->name))
544 1.1 christos {
545 1.1 christos *last = make_table (isa, rules, model);
546 1.1 christos last = &(*last)->next;
547 1.1 christos }
548 1.1 christos }
549 1.1 christos }
550 1.1 christos else
551 1.1 christos {
552 1.1 christos gen->tables = make_table (isa, rules, NULL);
553 1.1 christos }
554 1.1 christos return gen;
555 1.1 christos }
556 1.1 christos
557 1.1 christos
558 1.1 christos /****************************************************************/
559 1.1 christos
560 1.1 christos /* Is the bit, according to the decode rule, identical across all the
561 1.1 christos instructions? */
562 1.1 christos static int
563 1.1 christos insns_bit_useless (insn_list *insns, decode_table *rule, int bit_nr)
564 1.1 christos {
565 1.1 christos insn_list *entry;
566 1.1 christos int value = -1;
567 1.1 christos int is_useless = 1; /* cleared if something actually found */
568 1.1 christos
569 1.1 christos /* check the instructions for some constant value in at least one of
570 1.1 christos the bit fields */
571 1.1 christos for (entry = insns; entry != NULL; entry = entry->next)
572 1.1 christos {
573 1.1 christos insn_word_entry *word = entry->insn->word[rule->word_nr];
574 1.1 christos insn_bit_entry *bit = word->bit[bit_nr];
575 1.1 christos switch (bit->field->type)
576 1.1 christos {
577 1.1 christos case insn_field_invalid:
578 1.1 christos ASSERT (0);
579 1.1 christos break;
580 1.1 christos case insn_field_wild:
581 1.1 christos case insn_field_reserved:
582 1.1 christos /* neither useless or useful - ignore */
583 1.1 christos break;
584 1.1 christos case insn_field_int:
585 1.1 christos switch (rule->search)
586 1.1 christos {
587 1.1 christos case decode_find_strings:
588 1.1 christos /* an integer isn't a string */
589 1.1 christos return 1;
590 1.1 christos case decode_find_constants:
591 1.1 christos case decode_find_mixed:
592 1.1 christos /* an integer is useful if its value isn't the same
593 1.1 christos between all instructions. The first time through the
594 1.1 christos value is saved, the second time through (if the
595 1.1 christos values differ) it is marked as useful. */
596 1.1 christos if (value < 0)
597 1.1 christos value = bit->value;
598 1.1 christos else if (value != bit->value)
599 1.1 christos is_useless = 0;
600 1.1 christos break;
601 1.1 christos }
602 1.1 christos break;
603 1.1 christos case insn_field_string:
604 1.1 christos switch (rule->search)
605 1.1 christos {
606 1.1 christos case decode_find_strings:
607 1.1 christos /* at least one string, keep checking */
608 1.1 christos is_useless = 0;
609 1.1 christos break;
610 1.1 christos case decode_find_constants:
611 1.1 christos case decode_find_mixed:
612 1.1 christos if (filter_is_member (rule->constant_field_names,
613 1.1 christos bit->field->val_string))
614 1.1 christos /* a string field forced to constant? */
615 1.1 christos is_useless = 0;
616 1.1 christos else if (bit->field->conditions != NULL
617 1.1 christos && bit->field->conditions->test == insn_field_cond_eq
618 1.1 christos && bit->field->conditions->type == insn_field_cond_value)
619 1.1 christos {
620 1.1 christos int shift = bit->field->last - bit_nr;
621 1.1 christos int bitvalue = (bit->field->conditions->value >> shift) & 1;
622 1.1 christos
623 1.1 christos if (value < 0)
624 1.1 christos value = bitvalue;
625 1.1 christos else if (value != bitvalue)
626 1.1 christos is_useless = 0;
627 1.1 christos }
628 1.1 christos else if (rule->search == decode_find_constants)
629 1.1 christos /* the string field isn't constant */
630 1.1 christos return 1;
631 1.1 christos break;
632 1.1 christos }
633 1.1 christos }
634 1.1 christos }
635 1.1 christos
636 1.1 christos /* Given only one constant value has been found, check through all
637 1.1 christos the instructions to see if at least one conditional makes it
638 1.1 christos usefull */
639 1.1 christos if (value >= 0 && is_useless)
640 1.1 christos {
641 1.1 christos for (entry = insns; entry != NULL; entry = entry->next)
642 1.1 christos {
643 1.1 christos insn_word_entry *word = entry->insn->word[rule->word_nr];
644 1.1 christos insn_bit_entry *bit = word->bit[bit_nr];
645 1.1 christos switch (bit->field->type)
646 1.1 christos {
647 1.1 christos case insn_field_invalid:
648 1.1 christos ASSERT (0);
649 1.1 christos break;
650 1.1 christos case insn_field_wild:
651 1.1 christos case insn_field_reserved:
652 1.1 christos case insn_field_int:
653 1.1 christos /* already processed */
654 1.1 christos break;
655 1.1 christos case insn_field_string:
656 1.1 christos switch (rule->search)
657 1.1 christos {
658 1.1 christos case decode_find_strings:
659 1.1 christos case decode_find_constants:
660 1.1 christos /* already processed */
661 1.1 christos break;
662 1.1 christos case decode_find_mixed:
663 1.1 christos /* string field with conditions. If this condition
664 1.1 christos eliminates the value then the compare is useful */
665 1.1 christos if (bit->field->conditions != NULL)
666 1.1 christos {
667 1.1 christos insn_field_cond *condition;
668 1.1 christos int shift = bit->field->last - bit_nr;
669 1.1 christos for (condition = bit->field->conditions;
670 1.1 christos condition != NULL; condition = condition->next)
671 1.1 christos {
672 1.1 christos switch (condition->type)
673 1.1 christos {
674 1.1 christos case insn_field_cond_value:
675 1.1 christos switch (condition->test)
676 1.1 christos {
677 1.1 christos case insn_field_cond_ne:
678 1.1 christos if (((condition->value >> shift) & 1)
679 1.1 christos == (unsigned) value)
680 1.1 christos /* conditional field excludes the
681 1.1 christos current value */
682 1.1 christos is_useless = 0;
683 1.1 christos break;
684 1.1 christos case insn_field_cond_eq:
685 1.1 christos if (((condition->value >> shift) & 1)
686 1.1 christos != (unsigned) value)
687 1.1 christos /* conditional field requires the
688 1.1 christos current value */
689 1.1 christos is_useless = 0;
690 1.1 christos break;
691 1.1 christos }
692 1.1 christos break;
693 1.1 christos case insn_field_cond_field:
694 1.1 christos /* are these handled separatly? */
695 1.1 christos break;
696 1.1 christos }
697 1.1 christos }
698 1.1 christos }
699 1.1 christos }
700 1.1 christos }
701 1.1 christos }
702 1.1 christos }
703 1.1 christos
704 1.1 christos return is_useless;
705 1.1 christos }
706 1.1 christos
707 1.1 christos
708 1.1 christos /* go through a gen-table's list of instruction formats looking for a
709 1.1 christos range of bits that meet the decode table RULEs requirements */
710 1.1 christos
711 1.1 christos static opcode_field *
712 1.1 christos gen_entry_find_opcode_field (insn_list *insns,
713 1.1 christos decode_table *rule, int string_only)
714 1.1 christos {
715 1.1 christos opcode_field curr_opcode;
716 1.1 christos ASSERT (rule != NULL);
717 1.1 christos
718 1.1 christos memset (&curr_opcode, 0, sizeof (curr_opcode));
719 1.1 christos curr_opcode.word_nr = rule->word_nr;
720 1.1 christos curr_opcode.first = rule->first;
721 1.1 christos curr_opcode.last = rule->last;
722 1.1 christos
723 1.1 christos /* Try to reduce the size of first..last in accordance with the
724 1.1 christos decode rules */
725 1.1 christos
726 1.1 christos while (curr_opcode.first <= rule->last)
727 1.1 christos {
728 1.1 christos if (insns_bit_useless (insns, rule, curr_opcode.first))
729 1.1 christos curr_opcode.first++;
730 1.1 christos else
731 1.1 christos break;
732 1.1 christos }
733 1.1 christos while (curr_opcode.last >= rule->first)
734 1.1 christos {
735 1.1 christos if (insns_bit_useless (insns, rule, curr_opcode.last))
736 1.1 christos curr_opcode.last--;
737 1.1 christos else
738 1.1 christos break;
739 1.1 christos }
740 1.1 christos
741 1.1 christos /* did the final opcode field end up being empty? */
742 1.1 christos if (curr_opcode.first > curr_opcode.last)
743 1.1 christos {
744 1.1 christos return NULL;
745 1.1 christos }
746 1.1 christos ASSERT (curr_opcode.last >= rule->first);
747 1.1 christos ASSERT (curr_opcode.first <= rule->last);
748 1.1 christos ASSERT (curr_opcode.first <= curr_opcode.last);
749 1.1 christos
750 1.1 christos /* Ensure that, for the non string only case, the opcode includes
751 1.1 christos the range forced_first .. forced_last */
752 1.1 christos if (!string_only && curr_opcode.first > rule->force_first)
753 1.1 christos {
754 1.1 christos curr_opcode.first = rule->force_first;
755 1.1 christos }
756 1.1 christos if (!string_only && curr_opcode.last < rule->force_last)
757 1.1 christos {
758 1.1 christos curr_opcode.last = rule->force_last;
759 1.1 christos }
760 1.1 christos
761 1.1 christos /* For the string only case, force just the lower bound (so that the
762 1.1 christos shift can be eliminated) */
763 1.1 christos if (string_only && rule->force_last == options.insn_bit_size - 1)
764 1.1 christos {
765 1.1 christos curr_opcode.last = options.insn_bit_size - 1;
766 1.1 christos }
767 1.1 christos
768 1.1 christos /* handle any special cases */
769 1.1 christos switch (rule->type)
770 1.1 christos {
771 1.1 christos case normal_decode_rule:
772 1.1 christos /* let the above apply */
773 1.1 christos curr_opcode.nr_opcodes =
774 1.1 christos (1 << (curr_opcode.last - curr_opcode.first + 1));
775 1.1 christos break;
776 1.1 christos case boolean_rule:
777 1.1 christos curr_opcode.is_boolean = 1;
778 1.1 christos curr_opcode.boolean_constant = rule->constant;
779 1.1 christos curr_opcode.nr_opcodes = 2;
780 1.1 christos break;
781 1.1 christos }
782 1.1 christos
783 1.1 christos {
784 1.1 christos opcode_field *new_field = ZALLOC (opcode_field);
785 1.1 christos memcpy (new_field, &curr_opcode, sizeof (opcode_field));
786 1.1 christos return new_field;
787 1.1 christos }
788 1.1 christos }
789 1.1 christos
790 1.1 christos
791 1.1 christos static void
792 1.1 christos gen_entry_insert_insn (gen_entry *table,
793 1.1 christos insn_entry * old_insn,
794 1.1 christos int new_word_nr,
795 1.1 christos int new_nr_prefetched_words,
796 1.1 christos int new_opcode_nr, opcode_bits *new_bits)
797 1.1 christos {
798 1.1 christos gen_entry **entry = &table->entries;
799 1.1 christos
800 1.1 christos /* find the new table for this entry */
801 1.1 christos while ((*entry) != NULL && (*entry)->opcode_nr < new_opcode_nr)
802 1.1 christos {
803 1.1 christos entry = &(*entry)->sibling;
804 1.1 christos }
805 1.1 christos
806 1.1 christos if ((*entry) == NULL || (*entry)->opcode_nr != new_opcode_nr)
807 1.1 christos {
808 1.1 christos /* insert the missing entry */
809 1.1 christos gen_entry *new_entry = ZALLOC (gen_entry);
810 1.1 christos new_entry->sibling = (*entry);
811 1.1 christos (*entry) = new_entry;
812 1.1 christos table->nr_entries++;
813 1.1 christos /* fill it in */
814 1.1 christos new_entry->top = table->top;
815 1.1 christos new_entry->opcode_nr = new_opcode_nr;
816 1.1 christos new_entry->word_nr = new_word_nr;
817 1.1 christos new_entry->expanded_bits = new_bits;
818 1.1 christos new_entry->opcode_rule = table->opcode_rule->next;
819 1.1 christos new_entry->parent = table;
820 1.1 christos new_entry->nr_prefetched_words = new_nr_prefetched_words;
821 1.1 christos }
822 1.1 christos /* ASSERT new_bits == cur_entry bits */
823 1.1 christos ASSERT ((*entry) != NULL && (*entry)->opcode_nr == new_opcode_nr);
824 1.1 christos insn_list_insert (&(*entry)->insns, &(*entry)->nr_insns, old_insn, NULL, /* expanded_bits - only in final list */
825 1.1 christos NULL, /* opcodes - only in final list */
826 1.1 christos new_nr_prefetched_words, /* for this table */
827 1.1 christos report_duplicate_insns);
828 1.1 christos }
829 1.1 christos
830 1.1 christos
831 1.1 christos static void
832 1.1 christos gen_entry_expand_opcode (gen_entry *table,
833 1.1 christos insn_entry * instruction,
834 1.1 christos int bit_nr, int opcode_nr, opcode_bits *bits)
835 1.1 christos {
836 1.1 christos if (bit_nr > table->opcode->last)
837 1.1 christos {
838 1.1 christos /* Only include the hardwired bit information with an entry IF
839 1.1 christos that entry (and hence its functions) are being duplicated. */
840 1.1 christos if (options.trace.insn_expansion)
841 1.1 christos {
842 1.1 christos print_gen_entry_path (table->opcode_rule->line, table, notify);
843 1.1 christos notify (NULL, ": insert %d - %s.%s%s\n",
844 1.1 christos opcode_nr,
845 1.1 christos instruction->format_name,
846 1.1 christos instruction->name,
847 1.1 christos (table->opcode_rule->
848 1.1 christos with_duplicates ? " (duplicated)" : ""));
849 1.1 christos }
850 1.1 christos if (table->opcode_rule->with_duplicates)
851 1.1 christos {
852 1.1 christos gen_entry_insert_insn (table, instruction,
853 1.1 christos table->opcode->word_nr,
854 1.1 christos table->nr_prefetched_words, opcode_nr, bits);
855 1.1 christos }
856 1.1 christos else
857 1.1 christos {
858 1.1 christos gen_entry_insert_insn (table, instruction,
859 1.1 christos table->opcode->word_nr,
860 1.1 christos table->nr_prefetched_words, opcode_nr, NULL);
861 1.1 christos }
862 1.1 christos }
863 1.1 christos else
864 1.1 christos {
865 1.1 christos insn_word_entry *word = instruction->word[table->opcode->word_nr];
866 1.1 christos insn_field_entry *field = word->bit[bit_nr]->field;
867 1.1 christos int last_pos = ((field->last < table->opcode->last)
868 1.1 christos ? field->last : table->opcode->last);
869 1.1 christos int first_pos = ((field->first > table->opcode->first)
870 1.1 christos ? field->first : table->opcode->first);
871 1.1 christos int width = last_pos - first_pos + 1;
872 1.1 christos switch (field->type)
873 1.1 christos {
874 1.1 christos case insn_field_int:
875 1.1 christos {
876 1.1 christos int val;
877 1.1 christos val = sub_val (field->val_int, field->last, first_pos, last_pos);
878 1.1 christos gen_entry_expand_opcode (table, instruction,
879 1.1 christos last_pos + 1,
880 1.1 christos ((opcode_nr << width) | val), bits);
881 1.1 christos break;
882 1.1 christos }
883 1.1 christos default:
884 1.1 christos {
885 1.1 christos if (field->type == insn_field_reserved)
886 1.1 christos gen_entry_expand_opcode (table, instruction,
887 1.1 christos last_pos + 1,
888 1.1 christos ((opcode_nr << width)), bits);
889 1.1 christos else
890 1.1 christos {
891 1.1 christos int val;
892 1.1 christos int last_val = (table->opcode->is_boolean ? 2 : (1 << width));
893 1.1 christos for (val = 0; val < last_val; val++)
894 1.1 christos {
895 1.1 christos /* check to see if the value has been precluded
896 1.1 christos (by a conditional) in some way */
897 1.1 christos int is_precluded;
898 1.1 christos insn_field_cond *condition;
899 1.1 christos for (condition = field->conditions, is_precluded = 0;
900 1.1 christos condition != NULL && !is_precluded;
901 1.1 christos condition = condition->next)
902 1.1 christos {
903 1.1 christos switch (condition->type)
904 1.1 christos {
905 1.1 christos case insn_field_cond_value:
906 1.1 christos {
907 1.1 christos int value =
908 1.1 christos sub_val (condition->value, field->last,
909 1.1 christos first_pos, last_pos);
910 1.1 christos switch (condition->test)
911 1.1 christos {
912 1.1 christos case insn_field_cond_ne:
913 1.1 christos if (value == val)
914 1.1 christos is_precluded = 1;
915 1.1 christos break;
916 1.1 christos case insn_field_cond_eq:
917 1.1 christos if (value != val)
918 1.1 christos is_precluded = 1;
919 1.1 christos break;
920 1.1 christos }
921 1.1 christos break;
922 1.1 christos }
923 1.1 christos case insn_field_cond_field:
924 1.1 christos {
925 1.1 christos int value = -1;
926 1.1 christos opcode_bits *bit;
927 1.1 christos gen_entry *t = NULL;
928 1.1 christos /* Try to find a value for the
929 1.1 christos conditional by looking back through
930 1.1 christos the previously defined bits for one
931 1.1 christos that covers the designated
932 1.1 christos conditional field */
933 1.1 christos for (bit = bits; bit != NULL; bit = bit->next)
934 1.1 christos {
935 1.1 christos if (bit->field->word_nr ==
936 1.1 christos condition->field->word_nr
937 1.1 christos && bit->first <= condition->field->first
938 1.1 christos && bit->last >= condition->field->last)
939 1.1 christos {
940 1.1 christos /* the bit field fully specified
941 1.1 christos the conditional field's value */
942 1.1 christos value = sub_val (bit->value, bit->last,
943 1.1 christos condition->field->
944 1.1 christos first,
945 1.1 christos condition->field->
946 1.1 christos last);
947 1.1 christos }
948 1.1 christos }
949 1.1 christos /* Try to find a value by looking
950 1.1 christos through this and previous tables */
951 1.1 christos if (bit == NULL)
952 1.1 christos {
953 1.1 christos for (t = table;
954 1.1 christos t->parent != NULL; t = t->parent)
955 1.1 christos {
956 1.1 christos if (t->parent->opcode->word_nr ==
957 1.1 christos condition->field->word_nr
958 1.1 christos && t->parent->opcode->first <=
959 1.1 christos condition->field->first
960 1.1 christos && t->parent->opcode->last >=
961 1.1 christos condition->field->last)
962 1.1 christos {
963 1.1 christos /* the table entry fully
964 1.1 christos specified the condition
965 1.1 christos field's value */
966 1.1 christos /* extract the field's value
967 1.1 christos from the opcode */
968 1.1 christos value =
969 1.1 christos sub_val (t->opcode_nr,
970 1.1 christos t->parent->opcode->last,
971 1.1 christos condition->field->first,
972 1.1 christos condition->field->last);
973 1.1 christos /* this is a requirement of
974 1.1 christos a conditonal field
975 1.1 christos refering to another field */
976 1.1 christos ASSERT ((condition->field->first -
977 1.1 christos condition->field->last) ==
978 1.1 christos (first_pos - last_pos));
979 1.1 christos printf
980 1.1 christos ("value=%d, opcode_nr=%d, last=%d, [%d..%d]\n",
981 1.1 christos value, t->opcode_nr,
982 1.1 christos t->parent->opcode->last,
983 1.1 christos condition->field->first,
984 1.1 christos condition->field->last);
985 1.1 christos }
986 1.1 christos }
987 1.1 christos }
988 1.1 christos if (bit == NULL && t == NULL)
989 1.1 christos error (instruction->line,
990 1.1 christos "Conditional `%s' of field `%s' isn't expanded",
991 1.1 christos condition->string, field->val_string);
992 1.1 christos switch (condition->test)
993 1.1 christos {
994 1.1 christos case insn_field_cond_ne:
995 1.1 christos if (value == val)
996 1.1 christos is_precluded = 1;
997 1.1 christos break;
998 1.1 christos case insn_field_cond_eq:
999 1.1 christos if (value != val)
1000 1.1 christos is_precluded = 1;
1001 1.1 christos break;
1002 1.1 christos }
1003 1.1 christos break;
1004 1.1 christos }
1005 1.1 christos }
1006 1.1 christos }
1007 1.1 christos if (!is_precluded)
1008 1.1 christos {
1009 1.1 christos /* Only add additional hardwired bit
1010 1.1 christos information if the entry is not going to
1011 1.1 christos later be combined */
1012 1.1 christos if (table->opcode_rule->with_combine)
1013 1.1 christos {
1014 1.1 christos gen_entry_expand_opcode (table, instruction,
1015 1.1 christos last_pos + 1,
1016 1.1 christos ((opcode_nr << width) |
1017 1.1 christos val), bits);
1018 1.1 christos }
1019 1.1 christos else
1020 1.1 christos {
1021 1.1 christos opcode_bits *new_bits =
1022 1.1 christos new_opcode_bits (bits, val,
1023 1.1 christos first_pos, last_pos,
1024 1.1 christos field,
1025 1.1 christos table->opcode);
1026 1.1 christos gen_entry_expand_opcode (table, instruction,
1027 1.1 christos last_pos + 1,
1028 1.1 christos ((opcode_nr << width) |
1029 1.1 christos val), new_bits);
1030 1.1 christos }
1031 1.1 christos }
1032 1.1 christos }
1033 1.1 christos }
1034 1.1 christos }
1035 1.1 christos }
1036 1.1 christos }
1037 1.1 christos }
1038 1.1 christos
1039 1.1 christos static void
1040 1.1 christos gen_entry_insert_expanding (gen_entry *table, insn_entry * instruction)
1041 1.1 christos {
1042 1.1 christos gen_entry_expand_opcode (table,
1043 1.1 christos instruction,
1044 1.1 christos table->opcode->first, 0, table->expanded_bits);
1045 1.1 christos }
1046 1.1 christos
1047 1.1 christos
1048 1.1 christos static int
1049 1.1 christos insns_match_format_names (insn_list *insns, filter *format_names)
1050 1.1 christos {
1051 1.1 christos if (format_names != NULL)
1052 1.1 christos {
1053 1.1 christos insn_list *i;
1054 1.1 christos for (i = insns; i != NULL; i = i->next)
1055 1.1 christos {
1056 1.1 christos if (i->insn->format_name != NULL
1057 1.1 christos && !filter_is_member (format_names, i->insn->format_name))
1058 1.1 christos return 0;
1059 1.1 christos }
1060 1.1 christos }
1061 1.1 christos return 1;
1062 1.1 christos }
1063 1.1 christos
1064 1.1 christos static int
1065 1.1 christos table_matches_path (gen_entry *table, decode_path_list *paths)
1066 1.1 christos {
1067 1.1 christos if (paths == NULL)
1068 1.1 christos return 1;
1069 1.1 christos while (paths != NULL)
1070 1.1 christos {
1071 1.1 christos gen_entry *entry = table;
1072 1.1 christos decode_path *path = paths->path;
1073 1.1 christos while (1)
1074 1.1 christos {
1075 1.1 christos if (entry == NULL && path == NULL)
1076 1.1 christos return 1;
1077 1.1 christos if (entry == NULL || path == NULL)
1078 1.1 christos break;
1079 1.1 christos if (entry->opcode_nr != path->opcode_nr)
1080 1.1 christos break;
1081 1.1 christos entry = entry->parent;
1082 1.1 christos path = path->parent;
1083 1.1 christos }
1084 1.1 christos paths = paths->next;
1085 1.1 christos }
1086 1.1 christos return 0;
1087 1.1 christos }
1088 1.1 christos
1089 1.1 christos
1090 1.1 christos static int
1091 1.1 christos insns_match_conditions (insn_list *insns, decode_cond *conditions)
1092 1.1 christos {
1093 1.1 christos if (conditions != NULL)
1094 1.1 christos {
1095 1.1 christos insn_list *i;
1096 1.1 christos for (i = insns; i != NULL; i = i->next)
1097 1.1 christos {
1098 1.1 christos decode_cond *cond;
1099 1.1 christos for (cond = conditions; cond != NULL; cond = cond->next)
1100 1.1 christos {
1101 1.1 christos int bit_nr;
1102 1.1 christos if (i->insn->nr_words <= cond->word_nr)
1103 1.1 christos return 0;
1104 1.1 christos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
1105 1.1 christos {
1106 1.1 christos if (!cond->mask[bit_nr])
1107 1.1 christos continue;
1108 1.1 christos if (!i->insn->word[cond->word_nr]->bit[bit_nr]->mask)
1109 1.1 christos return 0;
1110 1.1 christos if ((i->insn->word[cond->word_nr]->bit[bit_nr]->value
1111 1.1 christos == cond->value[bit_nr]) == !cond->is_equal)
1112 1.1 christos return 0;
1113 1.1 christos }
1114 1.1 christos }
1115 1.1 christos }
1116 1.1 christos }
1117 1.1 christos return 1;
1118 1.1 christos }
1119 1.1 christos
1120 1.1 christos static int
1121 1.1 christos insns_match_nr_words (insn_list *insns, int nr_words)
1122 1.1 christos {
1123 1.1 christos insn_list *i;
1124 1.1 christos for (i = insns; i != NULL; i = i->next)
1125 1.1 christos {
1126 1.1 christos if (i->insn->nr_words < nr_words)
1127 1.1 christos return 0;
1128 1.1 christos }
1129 1.1 christos return 1;
1130 1.1 christos }
1131 1.1 christos
1132 1.1 christos static int
1133 1.1 christos insn_list_cmp (insn_list *l, insn_list *r)
1134 1.1 christos {
1135 1.1 christos while (1)
1136 1.1 christos {
1137 1.1 christos insn_entry *insn;
1138 1.1 christos if (l == NULL && r == NULL)
1139 1.1 christos return 0;
1140 1.1 christos if (l == NULL)
1141 1.1 christos return -1;
1142 1.1 christos if (r == NULL)
1143 1.1 christos return 1;
1144 1.1 christos if (l->insn != r->insn)
1145 1.1 christos return -1; /* somewhat arbitrary at present */
1146 1.1 christos /* skip this insn */
1147 1.1 christos insn = l->insn;
1148 1.1 christos while (l != NULL && l->insn == insn)
1149 1.1 christos l = l->next;
1150 1.1 christos while (r != NULL && r->insn == insn)
1151 1.1 christos r = r->next;
1152 1.1 christos }
1153 1.1 christos }
1154 1.1 christos
1155 1.1 christos
1156 1.1 christos
1157 1.1 christos static void
1158 1.1 christos gen_entry_expand_insns (gen_entry *table)
1159 1.1 christos {
1160 1.1 christos decode_table *opcode_rule;
1161 1.1 christos
1162 1.1 christos ASSERT (table->nr_insns >= 1);
1163 1.1 christos
1164 1.1 christos /* determine a valid opcode */
1165 1.1 christos for (opcode_rule = table->opcode_rule;
1166 1.1 christos opcode_rule != NULL; opcode_rule = opcode_rule->next)
1167 1.1 christos {
1168 1.1 christos char *discard_reason;
1169 1.1 christos if (table->top->model != NULL
1170 1.1 christos && opcode_rule->model_names != NULL
1171 1.1 christos && !filter_is_member (opcode_rule->model_names,
1172 1.1 christos table->top->model->name))
1173 1.1 christos {
1174 1.1 christos /* the rule isn't applicable to this processor */
1175 1.1 christos discard_reason = "wrong model";
1176 1.1 christos }
1177 1.1 christos else if (table->nr_insns == 1 && opcode_rule->conditions == NULL)
1178 1.1 christos {
1179 1.1 christos /* for safety, require a pre-codition when attempting to
1180 1.1 christos apply a rule to a single instruction */
1181 1.1 christos discard_reason = "need pre-condition when nr-insn == 1";
1182 1.1 christos }
1183 1.1 christos else if (table->nr_insns == 1 && !opcode_rule->with_duplicates)
1184 1.1 christos {
1185 1.1 christos /* Little point in expanding a single instruction when we're
1186 1.1 christos not duplicating the semantic functions that this table
1187 1.1 christos calls */
1188 1.1 christos discard_reason = "need duplication with nr-insns == 1";
1189 1.1 christos }
1190 1.1 christos else
1191 1.1 christos if (!insns_match_format_names
1192 1.1 christos (table->insns, opcode_rule->format_names))
1193 1.1 christos {
1194 1.1 christos discard_reason = "wrong format name";
1195 1.1 christos }
1196 1.1 christos else if (!insns_match_nr_words (table->insns, opcode_rule->word_nr + 1))
1197 1.1 christos {
1198 1.1 christos discard_reason = "wrong nr words";
1199 1.1 christos }
1200 1.1 christos else if (!table_matches_path (table, opcode_rule->paths))
1201 1.1 christos {
1202 1.1 christos discard_reason = "path failed";
1203 1.1 christos }
1204 1.1 christos else
1205 1.1 christos if (!insns_match_conditions (table->insns, opcode_rule->conditions))
1206 1.1 christos {
1207 1.1 christos discard_reason = "condition failed";
1208 1.1 christos }
1209 1.1 christos else
1210 1.1 christos {
1211 1.1 christos discard_reason = "no opcode field";
1212 1.1 christos table->opcode = gen_entry_find_opcode_field (table->insns,
1213 1.1 christos opcode_rule,
1214 1.1 christos table->nr_insns == 1 /*string-only */
1215 1.1 christos );
1216 1.1 christos if (table->opcode != NULL)
1217 1.1 christos {
1218 1.1 christos table->opcode_rule = opcode_rule;
1219 1.1 christos break;
1220 1.1 christos }
1221 1.1 christos }
1222 1.1 christos
1223 1.1 christos if (options.trace.rule_rejection)
1224 1.1 christos {
1225 1.1 christos print_gen_entry_path (opcode_rule->line, table, notify);
1226 1.1 christos notify (NULL, ": rule discarded - %s\n", discard_reason);
1227 1.1 christos }
1228 1.1 christos }
1229 1.1 christos
1230 1.1 christos /* did we find anything */
1231 1.1 christos if (opcode_rule == NULL)
1232 1.1 christos {
1233 1.1 christos /* the decode table failed, this set of instructions haven't
1234 1.1 christos been uniquely identified */
1235 1.1 christos if (table->nr_insns > 1)
1236 1.1 christos {
1237 1.1 christos print_gen_entry_insns (table, warning,
1238 1.1 christos "was not uniquely decoded",
1239 1.1 christos "decodes to the same entry");
1240 1.1 christos error (NULL, "");
1241 1.1 christos }
1242 1.1 christos return;
1243 1.1 christos }
1244 1.1 christos
1245 1.1 christos /* Determine the number of words that must have been prefetched for
1246 1.1 christos this table to function */
1247 1.1 christos if (table->parent == NULL)
1248 1.1 christos table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
1249 1.1 christos else if (table->opcode_rule->word_nr + 1 >
1250 1.1 christos table->parent->nr_prefetched_words)
1251 1.1 christos table->nr_prefetched_words = table->opcode_rule->word_nr + 1;
1252 1.1 christos else
1253 1.1 christos table->nr_prefetched_words = table->parent->nr_prefetched_words;
1254 1.1 christos
1255 1.1 christos /* back link what we found to its parent */
1256 1.1 christos if (table->parent != NULL)
1257 1.1 christos {
1258 1.1 christos ASSERT (table->parent->opcode != NULL);
1259 1.1 christos table->opcode->parent = table->parent->opcode;
1260 1.1 christos }
1261 1.1 christos
1262 1.1 christos /* report the rule being used to expand the instructions */
1263 1.1 christos if (options.trace.rule_selection)
1264 1.1 christos {
1265 1.1 christos print_gen_entry_path (table->opcode_rule->line, table, notify);
1266 1.1 christos notify (NULL,
1267 1.1 christos ": decode - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d\n",
1268 1.1 christos table->opcode->word_nr,
1269 1.1 christos i2target (options.hi_bit_nr, table->opcode->first),
1270 1.1 christos i2target (options.hi_bit_nr, table->opcode->last),
1271 1.1 christos i2target (options.hi_bit_nr, table->opcode_rule->first),
1272 1.1 christos i2target (options.hi_bit_nr, table->opcode_rule->last),
1273 1.1 christos table->opcode->nr_opcodes, table->nr_entries);
1274 1.1 christos }
1275 1.1 christos
1276 1.1 christos /* expand the raw instructions according to the opcode */
1277 1.1 christos {
1278 1.1 christos insn_list *entry;
1279 1.1 christos for (entry = table->insns; entry != NULL; entry = entry->next)
1280 1.1 christos {
1281 1.1 christos if (options.trace.insn_expansion)
1282 1.1 christos {
1283 1.1 christos print_gen_entry_path (table->opcode_rule->line, table, notify);
1284 1.1 christos notify (NULL, ": expand - %s.%s\n",
1285 1.1 christos entry->insn->format_name, entry->insn->name);
1286 1.1 christos }
1287 1.1 christos gen_entry_insert_expanding (table, entry->insn);
1288 1.1 christos }
1289 1.1 christos }
1290 1.1 christos
1291 1.1 christos /* dump the results */
1292 1.1 christos if (options.trace.entries)
1293 1.1 christos {
1294 1.1 christos gen_entry *entry;
1295 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
1296 1.1 christos {
1297 1.1 christos insn_list *l;
1298 1.1 christos print_gen_entry_path (table->opcode_rule->line, entry, notify);
1299 1.1 christos notify (NULL, ": %d - entries %d -",
1300 1.1 christos entry->opcode_nr, entry->nr_insns);
1301 1.1 christos for (l = entry->insns; l != NULL; l = l->next)
1302 1.1 christos notify (NULL, " %s.%s", l->insn->format_name, l->insn->name);
1303 1.1 christos notify (NULL, "\n");
1304 1.1 christos }
1305 1.1 christos }
1306 1.1 christos
1307 1.1 christos /* perform a combine pass if needed */
1308 1.1 christos if (table->opcode_rule->with_combine)
1309 1.1 christos {
1310 1.1 christos gen_entry *entry;
1311 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
1312 1.1 christos {
1313 1.1 christos if (entry->combined_parent == NULL)
1314 1.1 christos {
1315 1.1 christos gen_entry **last = &entry->combined_next;
1316 1.1 christos gen_entry *alt;
1317 1.1 christos for (alt = entry->sibling; alt != NULL; alt = alt->sibling)
1318 1.1 christos {
1319 1.1 christos if (alt->combined_parent == NULL
1320 1.1 christos && insn_list_cmp (entry->insns, alt->insns) == 0)
1321 1.1 christos {
1322 1.1 christos alt->combined_parent = entry;
1323 1.1 christos *last = alt;
1324 1.1 christos last = &alt->combined_next;
1325 1.1 christos }
1326 1.1 christos }
1327 1.1 christos }
1328 1.1 christos }
1329 1.1 christos if (options.trace.combine)
1330 1.1 christos {
1331 1.1 christos int nr_unique = 0;
1332 1.1 christos gen_entry *entry;
1333 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
1334 1.1 christos {
1335 1.1 christos if (entry->combined_parent == NULL)
1336 1.1 christos {
1337 1.1 christos insn_list *l;
1338 1.1 christos gen_entry *duplicate;
1339 1.1 christos nr_unique++;
1340 1.1 christos print_gen_entry_path (table->opcode_rule->line, entry,
1341 1.1 christos notify);
1342 1.1 christos for (duplicate = entry->combined_next; duplicate != NULL;
1343 1.1 christos duplicate = duplicate->combined_next)
1344 1.1 christos {
1345 1.1 christos notify (NULL, "+%d", duplicate->opcode_nr);
1346 1.1 christos }
1347 1.1 christos notify (NULL, ": entries %d -", entry->nr_insns);
1348 1.1 christos for (l = entry->insns; l != NULL; l = l->next)
1349 1.1 christos {
1350 1.1 christos notify (NULL, " %s.%s",
1351 1.1 christos l->insn->format_name, l->insn->name);
1352 1.1 christos }
1353 1.1 christos notify (NULL, "\n");
1354 1.1 christos }
1355 1.1 christos }
1356 1.1 christos print_gen_entry_path (table->opcode_rule->line, table, notify);
1357 1.1 christos notify (NULL,
1358 1.1 christos ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n",
1359 1.1 christos table->opcode->word_nr, i2target (options.hi_bit_nr,
1360 1.1 christos table->opcode->first),
1361 1.1 christos i2target (options.hi_bit_nr, table->opcode->last),
1362 1.1 christos i2target (options.hi_bit_nr, table->opcode_rule->first),
1363 1.1 christos i2target (options.hi_bit_nr, table->opcode_rule->last),
1364 1.1 christos table->opcode->nr_opcodes, table->nr_entries, nr_unique);
1365 1.1 christos }
1366 1.1 christos }
1367 1.1 christos
1368 1.1 christos /* Check that the rule did more than re-arange the order of the
1369 1.1 christos instructions */
1370 1.1 christos {
1371 1.1 christos gen_entry *entry;
1372 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
1373 1.1 christos {
1374 1.1 christos if (entry->combined_parent == NULL)
1375 1.1 christos {
1376 1.1 christos if (insn_list_cmp (table->insns, entry->insns) == 0)
1377 1.1 christos {
1378 1.1 christos print_gen_entry_path (table->opcode_rule->line, table,
1379 1.1 christos warning);
1380 1.1 christos warning (NULL,
1381 1.1 christos ": Applying rule just copied all instructions\n");
1382 1.1 christos print_gen_entry_insns (entry, warning, "Copied", NULL);
1383 1.1 christos error (NULL, "");
1384 1.1 christos }
1385 1.1 christos }
1386 1.1 christos }
1387 1.1 christos }
1388 1.1 christos
1389 1.1 christos /* if some form of expanded table, fill in the missing dots */
1390 1.1 christos switch (table->opcode_rule->gen)
1391 1.1 christos {
1392 1.1 christos case padded_switch_gen:
1393 1.1 christos case array_gen:
1394 1.1 christos case goto_switch_gen:
1395 1.1 christos if (!table->opcode->is_boolean)
1396 1.1 christos {
1397 1.1 christos gen_entry **entry = &table->entries;
1398 1.1 christos gen_entry *illegals = NULL;
1399 1.1 christos gen_entry **last_illegal = &illegals;
1400 1.1 christos int opcode_nr = 0;
1401 1.1 christos while (opcode_nr < table->opcode->nr_opcodes)
1402 1.1 christos {
1403 1.1 christos if ((*entry) == NULL || (*entry)->opcode_nr != opcode_nr)
1404 1.1 christos {
1405 1.1 christos /* missing - insert it under our feet at *entry */
1406 1.1 christos gen_entry_insert_insn (table, table->top->isa->illegal_insn, table->opcode->word_nr, 0, /* nr_prefetched_words == 0 for invalid */
1407 1.1 christos opcode_nr, NULL);
1408 1.1 christos ASSERT ((*entry) != NULL);
1409 1.1 christos ASSERT ((*entry)->opcode_nr == opcode_nr);
1410 1.1 christos (*last_illegal) = *entry;
1411 1.1 christos (*last_illegal)->combined_parent = illegals;
1412 1.1 christos last_illegal = &(*last_illegal)->combined_next;
1413 1.1 christos }
1414 1.1 christos entry = &(*entry)->sibling;
1415 1.1 christos opcode_nr++;
1416 1.1 christos }
1417 1.1 christos /* oops, will have pointed the first illegal insn back to
1418 1.1 christos its self. Fix this */
1419 1.1 christos if (illegals != NULL)
1420 1.1 christos illegals->combined_parent = NULL;
1421 1.1 christos }
1422 1.1 christos break;
1423 1.1 christos case switch_gen:
1424 1.1 christos case invalid_gen:
1425 1.1 christos /* ignore */
1426 1.1 christos break;
1427 1.1 christos }
1428 1.1 christos
1429 1.1 christos /* and do the same for the newly created sub entries but *only*
1430 1.1 christos expand entries that haven't been combined. */
1431 1.1 christos {
1432 1.1 christos gen_entry *entry;
1433 1.1 christos for (entry = table->entries; entry != NULL; entry = entry->sibling)
1434 1.1 christos {
1435 1.1 christos if (entry->combined_parent == NULL)
1436 1.1 christos {
1437 1.1 christos gen_entry_expand_insns (entry);
1438 1.1 christos }
1439 1.1 christos }
1440 1.1 christos }
1441 1.1 christos }
1442 1.1 christos
1443 1.1 christos void
1444 1.1 christos gen_tables_expand_insns (gen_table *gen)
1445 1.1 christos {
1446 1.1 christos gen_list *entry;
1447 1.1 christos for (entry = gen->tables; entry != NULL; entry = entry->next)
1448 1.1 christos {
1449 1.1 christos gen_entry_expand_insns (entry->table);
1450 1.1 christos }
1451 1.1 christos }
1452 1.1 christos
1453 1.1 christos
1454 1.1 christos /* create a list of all the semantic functions that need to be
1455 1.1 christos generated. Eliminate any duplicates. Verify that the decode stage
1456 1.1 christos worked. */
1457 1.1 christos
1458 1.1 christos static void
1459 1.1 christos make_gen_semantics_list (lf *file, gen_entry *entry, int depth, void *data)
1460 1.1 christos {
1461 1.1 christos gen_table *gen = (gen_table *) data;
1462 1.1 christos insn_list *insn;
1463 1.1 christos /* Not interested in an entrie that have been combined into some
1464 1.1 christos other entry at the same level */
1465 1.1 christos if (entry->combined_parent != NULL)
1466 1.1 christos return;
1467 1.1 christos
1468 1.1 christos /* a leaf should contain exactly one instruction. If not the decode
1469 1.1 christos stage failed. */
1470 1.1 christos ASSERT (entry->nr_insns == 1);
1471 1.1 christos
1472 1.1 christos /* Enter this instruction into the list of semantic functions. */
1473 1.1 christos insn = insn_list_insert (&gen->semantics, &gen->nr_semantics,
1474 1.1 christos entry->insns->insn,
1475 1.1 christos entry->expanded_bits,
1476 1.1 christos entry->parent->opcode,
1477 1.1 christos entry->insns->nr_prefetched_words,
1478 1.1 christos merge_duplicate_insns);
1479 1.1 christos /* point the table entry at the real semantic function */
1480 1.1 christos ASSERT (insn != NULL);
1481 1.1 christos entry->insns->semantic = insn;
1482 1.1 christos }
1483 1.1 christos
1484 1.1 christos
1485 1.1 christos void
1486 1.1 christos gen_tables_expand_semantics (gen_table *gen)
1487 1.1 christos {
1488 1.1 christos gen_list *entry;
1489 1.1 christos for (entry = gen->tables; entry != NULL; entry = entry->next)
1490 1.1 christos {
1491 1.1 christos gen_entry_traverse_tree (NULL, entry->table, 1, /* depth */
1492 1.1 christos NULL, /* start-handler */
1493 1.1 christos make_gen_semantics_list, /* leaf-handler */
1494 1.1 christos NULL, /* end-handler */
1495 1.1 christos gen); /* data */
1496 1.1 christos }
1497 1.1 christos }
1498 1.1 christos
1499 1.1 christos
1500 1.1 christos
1501 1.1 christos #ifdef MAIN
1502 1.1 christos
1503 1.1 christos
1504 1.1 christos static void
1505 1.1 christos dump_opcode_field (lf *file,
1506 1.1 christos char *prefix,
1507 1.1 christos opcode_field *field, char *suffix, int levels)
1508 1.1 christos {
1509 1.1 christos lf_printf (file, "%s(opcode_field *) 0x%lx", prefix, (long) field);
1510 1.1 christos if (levels && field != NULL)
1511 1.1 christos {
1512 1.1 christos lf_indent (file, +1);
1513 1.1 christos lf_printf (file, "\n(first %d)", field->first);
1514 1.1 christos lf_printf (file, "\n(last %d)", field->last);
1515 1.1 christos lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes);
1516 1.1 christos lf_printf (file, "\n(is_boolean %d)", field->is_boolean);
1517 1.1 christos lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant);
1518 1.1 christos dump_opcode_field (file, "\n(parent ", field->parent, ")", levels - 1);
1519 1.1 christos lf_indent (file, -1);
1520 1.1 christos }
1521 1.1 christos lf_printf (file, "%s", suffix);
1522 1.1 christos }
1523 1.1 christos
1524 1.1 christos
1525 1.1 christos static void
1526 1.1 christos dump_opcode_bits (lf *file,
1527 1.1 christos char *prefix, opcode_bits *bits, char *suffix, int levels)
1528 1.1 christos {
1529 1.1 christos lf_printf (file, "%s(opcode_bits *) 0x%lx", prefix, (long) bits);
1530 1.1 christos
1531 1.1 christos if (levels && bits != NULL)
1532 1.1 christos {
1533 1.1 christos lf_indent (file, +1);
1534 1.1 christos lf_printf (file, "\n(value %d)", bits->value);
1535 1.1 christos dump_opcode_field (file, "\n(opcode ", bits->opcode, ")", 0);
1536 1.1 christos dump_insn_field (file, "\n(field ", bits->field, ")");
1537 1.1 christos dump_opcode_bits (file, "\n(next ", bits->next, ")", levels - 1);
1538 1.1 christos lf_indent (file, -1);
1539 1.1 christos }
1540 1.1 christos lf_printf (file, "%s", suffix);
1541 1.1 christos }
1542 1.1 christos
1543 1.1 christos
1544 1.1 christos
1545 1.1 christos static void
1546 1.1 christos dump_insn_list (lf *file, char *prefix, insn_list *entry, char *suffix)
1547 1.1 christos {
1548 1.1 christos lf_printf (file, "%s(insn_list *) 0x%lx", prefix, (long) entry);
1549 1.1 christos
1550 1.1 christos if (entry != NULL)
1551 1.1 christos {
1552 1.1 christos lf_indent (file, +1);
1553 1.1 christos dump_insn_entry (file, "\n(insn ", entry->insn, ")");
1554 1.1 christos lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
1555 1.1 christos lf_indent (file, -1);
1556 1.1 christos }
1557 1.1 christos lf_printf (file, "%s", suffix);
1558 1.1 christos }
1559 1.1 christos
1560 1.1 christos
1561 1.1 christos static void
1562 1.1 christos dump_insn_word_entry_list_entries (lf *file,
1563 1.1 christos char *prefix,
1564 1.1 christos insn_list *entry, char *suffix)
1565 1.1 christos {
1566 1.1 christos lf_printf (file, "%s", prefix);
1567 1.1 christos while (entry != NULL)
1568 1.1 christos {
1569 1.1 christos dump_insn_list (file, "\n(", entry, ")");
1570 1.1 christos entry = entry->next;
1571 1.1 christos }
1572 1.1 christos lf_printf (file, "%s", suffix);
1573 1.1 christos }
1574 1.1 christos
1575 1.1 christos
1576 1.1 christos static void
1577 1.1 christos dump_gen_entry (lf *file,
1578 1.1 christos char *prefix, gen_entry *table, char *suffix, int levels)
1579 1.1 christos {
1580 1.1 christos
1581 1.1 christos lf_printf (file, "%s(gen_entry *) 0x%lx", prefix, (long) table);
1582 1.1 christos
1583 1.1 christos if (levels && table !=NULL)
1584 1.1 christos {
1585 1.1 christos
1586 1.1 christos lf_indent (file, +1);
1587 1.1 christos lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr);
1588 1.1 christos lf_printf (file, "\n(word_nr %d)", table->word_nr);
1589 1.1 christos dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")",
1590 1.1 christos -1);
1591 1.1 christos lf_printf (file, "\n(nr_insns %d)", table->nr_insns);
1592 1.1 christos dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns,
1593 1.1 christos ")");
1594 1.1 christos dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")");
1595 1.1 christos dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0);
1596 1.1 christos lf_printf (file, "\n(nr_entries %d)", table->nr_entries);
1597 1.1 christos dump_gen_entry (file, "\n(entries ", table->entries, ")",
1598 1.1 christos table->nr_entries);
1599 1.1 christos dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1);
1600 1.1 christos dump_gen_entry (file, "\n(parent ", table->parent, ")", 0);
1601 1.1 christos lf_indent (file, -1);
1602 1.1 christos }
1603 1.1 christos lf_printf (file, "%s", suffix);
1604 1.1 christos }
1605 1.1 christos
1606 1.1 christos static void
1607 1.1 christos dump_gen_list (lf *file,
1608 1.1 christos char *prefix, gen_list *entry, char *suffix, int levels)
1609 1.1 christos {
1610 1.1 christos while (entry != NULL)
1611 1.1 christos {
1612 1.1 christos lf_printf (file, "%s(gen_list *) 0x%lx", prefix, (long) entry);
1613 1.1 christos dump_gen_entry (file, "\n(", entry->table, ")", levels);
1614 1.1 christos lf_printf (file, "\n(next (gen_list *) 0x%lx)", (long) entry->next);
1615 1.1 christos lf_printf (file, "%s", suffix);
1616 1.1 christos }
1617 1.1 christos }
1618 1.1 christos
1619 1.1 christos
1620 1.1 christos static void
1621 1.1 christos dump_gen_table (lf *file,
1622 1.1 christos char *prefix, gen_table *gen, char *suffix, int levels)
1623 1.1 christos {
1624 1.1 christos lf_printf (file, "%s(gen_table *) 0x%lx", prefix, (long) gen);
1625 1.1 christos lf_printf (file, "\n(isa (insn_table *) 0x%lx)", (long) gen->isa);
1626 1.1 christos lf_printf (file, "\n(rules (decode_table *) 0x%lx)", (long) gen->rules);
1627 1.1 christos dump_gen_list (file, "\n(", gen->tables, ")", levels);
1628 1.1 christos lf_printf (file, "%s", suffix);
1629 1.1 christos }
1630 1.1 christos
1631 1.1 christos
1632 1.1 christos igen_options options;
1633 1.1 christos
1634 1.1 christos int
1635 1.1 christos main (int argc, char **argv)
1636 1.1 christos {
1637 1.1 christos decode_table *decode_rules;
1638 1.1 christos insn_table *instructions;
1639 1.1 christos gen_table *gen;
1640 1.1 christos lf *l;
1641 1.1 christos
1642 1.1 christos if (argc != 7)
1643 1.1 christos error (NULL,
1644 1.1 christos "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n");
1645 1.1 christos
1646 1.1 christos INIT_OPTIONS (options);
1647 1.1 christos
1648 1.1 christos filter_parse (&options.flags_filter, argv[1]);
1649 1.1 christos
1650 1.1 christos options.hi_bit_nr = a2i (argv[2]);
1651 1.1 christos options.insn_bit_size = a2i (argv[3]);
1652 1.1 christos options.insn_specifying_widths = a2i (argv[4]);
1653 1.1 christos ASSERT (options.hi_bit_nr < options.insn_bit_size);
1654 1.1 christos
1655 1.1 christos instructions = load_insn_table (argv[6], NULL);
1656 1.1 christos decode_rules = load_decode_table (argv[5]);
1657 1.1 christos gen = make_gen_tables (instructions, decode_rules);
1658 1.1 christos
1659 1.1 christos gen_tables_expand_insns (gen);
1660 1.1 christos
1661 1.1 christos l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
1662 1.1 christos
1663 1.1 christos dump_gen_table (l, "(", gen, ")\n", -1);
1664 1.1 christos return 0;
1665 1.1 christos }
1666 1.1 christos
1667 1.1 christos #endif
1668