Commit | Line | Data |
---|---|---|
feaee4bd AC |
1 | /* The IGEN simulator generator for GDB, the GNU Debugger. |
2 | ||
3 | Copyright 2002 Free Software Foundation, Inc. | |
4 | ||
5 | Contributed by Andrew Cagney. | |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program; if not, write to the Free Software | |
21 | Foundation, Inc., 59 Temple Place - Suite 330, | |
22 | Boston, MA 02111-1307, USA. */ | |
23 | ||
c906108c SS |
24 | |
25 | /* load the opcode stat structure */ | |
26 | ||
27 | #include "misc.h" | |
28 | #include "lf.h" | |
29 | #include "table.h" | |
30 | #include "filter.h" | |
31 | ||
32 | #include "igen.h" | |
33 | ||
34 | #include "ld-decode.h" | |
35 | ||
36 | #ifndef NULL | |
37 | #define NULL 0 | |
38 | #endif | |
39 | ||
40 | ||
41 | static const name_map decode_type_map[] = { | |
42 | { "normal", normal_decode_rule }, | |
43 | { "boolean", boolean_rule }, | |
44 | { NULL, normal_decode_rule }, | |
45 | }; | |
46 | ||
47 | static const name_map decode_gen_map[] = { | |
48 | { "array", array_gen }, | |
49 | { "switch", switch_gen }, | |
50 | { "padded-switch", padded_switch_gen }, | |
51 | { "goto-switch", goto_switch_gen }, | |
52 | { NULL, -1 }, | |
53 | }; | |
54 | ||
55 | static const name_map decode_reserved_map[] = { | |
56 | { "zero-reserved", 1 }, | |
57 | { NULL, 0 }, | |
58 | }; | |
59 | ||
60 | static const name_map decode_duplicates_map[] = { | |
61 | { "duplicate", 1 }, | |
62 | { NULL, 0 }, | |
63 | }; | |
64 | ||
65 | static const name_map decode_combine_map[] = { | |
66 | { "combine", 1 }, | |
67 | { NULL, 0 }, | |
68 | }; | |
69 | ||
70 | static const name_map decode_search_map[] = { | |
71 | { "constants", decode_find_constants }, | |
72 | { "mixed", decode_find_mixed }, | |
73 | { "strings", decode_find_strings }, | |
74 | { NULL, decode_find_mixed }, | |
75 | }; | |
76 | ||
77 | ||
78 | static void | |
79 | set_bits (int bit[max_insn_bit_size], | |
80 | unsigned64 value) | |
81 | { | |
82 | int bit_nr; | |
83 | for (bit_nr = 0; bit_nr < max_insn_bit_size; bit_nr++) | |
84 | { | |
85 | if (bit_nr < options.insn_bit_size) | |
86 | bit[bit_nr] = (value >> (options.insn_bit_size - bit_nr - 1)) & 1; | |
87 | else | |
88 | bit[bit_nr] = 0; | |
89 | } | |
90 | } | |
91 | ||
92 | decode_table * | |
93 | load_decode_table(char *file_name) | |
94 | { | |
95 | table *file = table_open (file_name); | |
96 | table_entry *entry; | |
97 | decode_table *table = NULL; | |
98 | decode_table **curr_rule = &table; | |
99 | while ((entry = table_read (file)) != NULL) | |
100 | { | |
101 | char *decode_options = entry->field[decode_options_field]; | |
102 | decode_table *new_rule = ZALLOC (decode_table); | |
103 | if (entry->nr_fields < min_nr_decode_fields) | |
104 | error (entry->line, "Missing decode table fields\n"); | |
105 | new_rule->line = entry->line; | |
106 | ||
107 | /* the options field */ | |
108 | new_rule->type = name2i (decode_options, decode_type_map); | |
109 | if (options.decode.overriding_gen != NULL) | |
110 | new_rule->gen = name2i (options.decode.overriding_gen, decode_gen_map); | |
111 | else | |
112 | new_rule->gen = name2i (decode_options, decode_gen_map); | |
113 | if (new_rule->gen == padded_switch_gen | |
114 | && options.decode.switch_as_goto) | |
115 | new_rule->gen = goto_switch_gen; | |
116 | if (options.decode.zero_reserved) | |
117 | new_rule->with_zero_reserved = 1; | |
118 | else | |
119 | new_rule->with_zero_reserved = name2i (decode_options, decode_reserved_map); | |
120 | if (options.decode.duplicate) | |
121 | new_rule->with_duplicates = 1; | |
122 | else | |
123 | new_rule->with_duplicates = name2i (decode_options, decode_duplicates_map); | |
124 | if (options.decode.combine) | |
125 | new_rule->with_combine = 1; | |
126 | else | |
127 | new_rule->with_combine = name2i (decode_options, decode_combine_map); | |
128 | if (new_rule->type == boolean_rule) | |
129 | { | |
130 | char *chp = decode_options; | |
131 | while (*chp != '\0') | |
132 | { | |
133 | if (isdigit (*chp)) | |
134 | { | |
135 | new_rule->constant = a2i (chp); | |
136 | break; | |
137 | } | |
138 | chp = skip_to_separator (chp, ","); | |
139 | chp = skip_spaces (chp); | |
140 | } | |
141 | } | |
142 | ||
143 | /* First and last */ | |
144 | if (entry->nr_fields > decode_first_field | |
145 | && strlen (entry->field[decode_first_field]) > 0) | |
146 | { | |
147 | new_rule->first = target_a2i (options.hi_bit_nr, | |
148 | entry->field[decode_first_field]); | |
149 | if (new_rule->first < 0 || new_rule->first >= options.insn_bit_size) | |
150 | error (new_rule->line, "First field out of range\n"); | |
151 | } | |
152 | else | |
153 | new_rule->first = 0; | |
154 | if (entry->nr_fields > decode_last_field | |
155 | && strlen (entry->field[decode_last_field]) > 0) | |
156 | { | |
157 | new_rule->last = target_a2i (options.hi_bit_nr, | |
158 | entry->field[decode_last_field]); | |
159 | if (new_rule->last < 0 || new_rule->last >= options.insn_bit_size) | |
160 | error (new_rule->line, "Last field out of range\n"); | |
161 | } | |
162 | else | |
163 | new_rule->last = options.insn_bit_size - 1; | |
164 | if (new_rule->first > new_rule->last) | |
165 | error (new_rule->line, "First must preceed last\n"); | |
166 | ||
167 | /* force first/last, with default values based on first/last */ | |
168 | if (entry->nr_fields > decode_force_first_field | |
169 | && strlen (entry->field[decode_force_first_field]) > 0) | |
170 | { | |
171 | new_rule->force_first = target_a2i (options.hi_bit_nr, | |
172 | entry->field[decode_force_first_field]); | |
173 | if (new_rule->force_first < new_rule->first | |
174 | || new_rule->force_first > new_rule->last + 1) | |
175 | error (new_rule->line, "Force first out of range\n"); | |
176 | } | |
177 | else | |
178 | new_rule->force_first = new_rule->last + 1; | |
179 | if (entry->nr_fields > decode_force_last_field | |
180 | && strlen (entry->field[decode_force_last_field]) > 0) | |
181 | { | |
182 | new_rule->force_last = target_a2i (options.hi_bit_nr, | |
183 | entry->field[decode_force_last_field]); | |
184 | if (new_rule->force_last > new_rule->last | |
185 | || new_rule->force_last < new_rule->first - 1) | |
186 | error (new_rule->line, "Force-last out of range\n"); | |
187 | } | |
188 | else | |
189 | new_rule->force_last = new_rule->first - 1; | |
190 | ||
191 | /* fields to be treated as constant */ | |
192 | if (entry->nr_fields > decode_constant_field_names_field) | |
193 | filter_parse (&new_rule->constant_field_names, | |
194 | entry->field[decode_constant_field_names_field]); | |
195 | ||
196 | /* applicable word nr */ | |
197 | if (entry->nr_fields > decode_word_nr_field) | |
198 | new_rule->word_nr = a2i (entry->field[decode_word_nr_field]); | |
199 | ||
200 | /* required instruction format names */ | |
201 | if (entry->nr_fields > decode_format_names_field) | |
202 | filter_parse (&new_rule->format_names, | |
203 | entry->field[decode_format_names_field]); | |
204 | ||
205 | /* required processor models */ | |
206 | if (entry->nr_fields > decode_model_names_field) | |
207 | filter_parse (&new_rule->model_names, | |
208 | entry->field[decode_model_names_field]); | |
209 | ||
210 | /* required paths */ | |
211 | if (entry->nr_fields > decode_paths_field | |
212 | && strlen (entry->field[decode_paths_field]) > 0) | |
213 | { | |
214 | decode_path_list **last = &new_rule->paths; | |
215 | char *chp = entry->field[decode_paths_field]; | |
216 | do | |
217 | { | |
218 | (*last) = ZALLOC (decode_path_list); | |
219 | /* extra root/zero entry */ | |
220 | (*last)->path = ZALLOC (decode_path); | |
221 | do | |
222 | { | |
223 | decode_path *entry = ZALLOC (decode_path); | |
224 | entry->opcode_nr = a2i (chp); | |
225 | entry->parent = (*last)->path; | |
226 | (*last)->path = entry; | |
227 | chp = skip_digits (chp); | |
228 | chp = skip_spaces (chp); | |
229 | } | |
230 | while (*chp == '.'); | |
231 | last = &(*last)->next; | |
232 | } | |
233 | while (*chp == ','); | |
234 | if (*chp != '\0') | |
235 | error (entry->line, "Invalid path field\n"); | |
236 | } | |
237 | ||
238 | /* collect up the list of optional special conditions applicable | |
239 | to the rule */ | |
240 | { | |
241 | int field_nr = nr_decode_fields; | |
242 | while (entry->nr_fields > field_nr) | |
243 | { | |
244 | decode_cond *cond = ZALLOC (decode_cond); | |
245 | decode_cond **last; | |
246 | if (entry->nr_fields > field_nr + decode_cond_mask_field) | |
247 | set_bits (cond->mask, a2i (entry->field[field_nr + decode_cond_mask_field])); | |
248 | if (entry->nr_fields > field_nr + decode_cond_value_field) | |
249 | { | |
250 | if (entry->field[field_nr + decode_cond_value_field][0] == '!') | |
251 | { | |
252 | cond->is_equal = 0; | |
253 | set_bits (cond->value, a2i (entry->field[field_nr + decode_cond_value_field] + 1)); | |
254 | } | |
255 | else | |
256 | { | |
257 | cond->is_equal = 1; | |
258 | set_bits (cond->value, a2i (entry->field[field_nr + decode_cond_value_field])); | |
259 | } | |
260 | } | |
261 | if (entry->nr_fields > field_nr + decode_cond_word_nr_field) | |
262 | cond->word_nr = a2i (entry->field[field_nr + decode_cond_word_nr_field]); | |
263 | field_nr += nr_decode_cond_fields; | |
264 | /* insert it */ | |
265 | last = &new_rule->conditions; | |
266 | while (*last != NULL) | |
267 | last = &(*last)->next; | |
268 | *last = cond; | |
269 | } | |
270 | } | |
271 | *curr_rule = new_rule; | |
272 | curr_rule = &new_rule->next; | |
273 | } | |
274 | return table; | |
275 | } | |
276 | ||
277 | ||
278 | int | |
279 | decode_table_max_word_nr (decode_table *entry) | |
280 | { | |
281 | int max_word_nr = 0; | |
282 | while (entry != NULL) | |
283 | { | |
284 | decode_cond *cond; | |
285 | if (entry->word_nr > max_word_nr) | |
286 | max_word_nr = entry->word_nr; | |
287 | for (cond = entry->conditions; cond != NULL; cond = cond->next) | |
288 | { | |
289 | if (cond->word_nr > max_word_nr) | |
290 | max_word_nr = cond->word_nr; | |
291 | } | |
292 | entry = entry->next; | |
293 | } | |
294 | return max_word_nr; | |
295 | } | |
296 | ||
297 | ||
298 | ||
299 | static void | |
300 | dump_decode_cond (lf *file, | |
301 | char *prefix, | |
302 | decode_cond *cond, | |
303 | char *suffix) | |
304 | { | |
305 | lf_printf (file, "%s(decode_cond *) 0x%lx", prefix, (long) cond); | |
306 | if (cond != NULL) | |
307 | { | |
308 | lf_indent (file, +1); | |
309 | lf_printf (file, "\n(word_nr %d)", cond->word_nr); | |
310 | lf_printf (file, "\n(mask 0x%lx)", (long) cond->mask); | |
311 | lf_printf (file, "\n(value 0x%lx)", (long) cond->value); | |
312 | lf_printf (file, "\n(is_equal 0x%lx)", (long) cond->is_equal); | |
313 | lf_printf (file, "\n(next (decode_cond *) 0%lx)", (long) cond->next); | |
314 | lf_indent (file, -1); | |
315 | } | |
316 | lf_printf (file, "%s", suffix); | |
317 | } | |
318 | ||
319 | ||
320 | static void | |
321 | dump_decode_conds (lf *file, | |
322 | char *prefix, | |
323 | decode_cond *cond, | |
324 | char *suffix) | |
325 | { | |
326 | lf_printf (file, "%s(decode_cond *) 0x%lx", prefix, (long) cond); | |
327 | while (cond != NULL) | |
328 | { | |
329 | dump_decode_cond (file, "\n(", cond, ")"); | |
330 | cond = cond->next; | |
331 | } | |
332 | lf_printf (file, "%s", suffix); | |
333 | } | |
334 | ||
335 | ||
336 | void | |
337 | dump_decode_rule (lf *file, | |
338 | char *prefix, | |
339 | decode_table *rule, | |
340 | char *suffix) | |
341 | { | |
342 | lf_printf (file, "%s(decode_table *) 0x%lx", prefix, (long) rule); | |
343 | if (rule != NULL) | |
344 | { | |
345 | lf_indent (file, +1); | |
346 | dump_line_ref (file, "\n(line ", rule->line, ")"); | |
347 | lf_printf (file, "\n(type %s)", i2name(rule->type, decode_type_map)); | |
348 | lf_printf (file, "\n(gen %s)", i2name(rule->gen, decode_gen_map)); | |
349 | lf_printf (file, "\n(first %d)", rule->first); | |
350 | lf_printf (file, "\n(last %d)", rule->last); | |
351 | lf_printf (file, "\n(force_first %d)", rule->force_first); | |
352 | lf_printf (file, "\n(force_last %d)", rule->force_last); | |
353 | dump_filter (file, "\n(constant_field_names \"", rule->constant_field_names, "\")"); | |
354 | lf_printf (file, "\n(constant 0x%x)", rule->constant); | |
355 | lf_printf (file, "\n(word_nr %d)", rule->word_nr); | |
356 | lf_printf (file, "\n(with_zero_reserved %d)", rule->with_zero_reserved); | |
357 | lf_printf (file, "\n(with_duplicates %d)", rule->with_duplicates); | |
358 | lf_printf (file, "\n(with_combine %d)", rule->with_combine); | |
359 | dump_filter (file, "\n(format_names \"", rule->format_names, "\")"); | |
360 | dump_filter (file, "\n(model_names \"", rule->model_names, "\")"); | |
361 | dump_decode_conds (file, "\n(conditions ", rule->conditions, ")"); | |
362 | lf_printf (file, "\n(next 0x%lx)", (long) rule->next); | |
363 | lf_indent (file, -1); | |
364 | } | |
365 | lf_printf (file, "%s", suffix); | |
366 | } | |
367 | ||
368 | ||
369 | #ifdef MAIN | |
370 | ||
371 | static void | |
372 | dump_decode_rules (lf *file, | |
373 | char *prefix, | |
374 | decode_table *rule, | |
375 | char *suffix) | |
376 | { | |
377 | lf_printf (file, "%s", prefix); | |
378 | while (rule != NULL) | |
379 | { | |
380 | lf_indent (file, +1); | |
381 | dump_decode_rule (file, "\n(", rule, ")"); | |
382 | lf_indent (file, -1); | |
383 | rule = rule->next; | |
384 | } | |
385 | lf_printf (file, "%s", suffix); | |
386 | } | |
387 | ||
388 | igen_options options; | |
389 | ||
390 | int | |
391 | main(int argc, char **argv) | |
392 | { | |
393 | lf *l; | |
394 | decode_table *rules; | |
395 | ||
396 | INIT_OPTIONS (options); | |
397 | ||
398 | if (argc != 3) | |
399 | error (NULL, "Usage: decode <decode-file> <hi-bit-nr>\n"); | |
400 | ||
401 | options.hi_bit_nr = a2i (argv[2]); | |
402 | rules = load_decode_table (argv[1]); | |
403 | l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn"); | |
404 | dump_decode_rules (l, "(rules ", rules, ")\n"); | |
405 | ||
406 | return 0; | |
407 | } | |
408 | #endif |