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