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