Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1998 Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
22 | ||
23 | typedef unsigned64 insn_uint; | |
24 | ||
25 | ||
26 | /* Common among most entries: | |
27 | ||
28 | All non instruction records have the format: | |
29 | ||
30 | <...> ::= | |
31 | ":" <record-name> | |
32 | ":" <filter-flags> | |
33 | ":" <filter-models> | |
34 | ":" ... | |
35 | ||
36 | */ | |
37 | ||
38 | enum { | |
39 | record_type_field = 1, | |
40 | old_record_type_field = 2, | |
41 | record_filter_flags_field = 2, | |
42 | record_filter_models_field = 3, | |
43 | }; | |
44 | ||
45 | ||
46 | /* Include: | |
47 | ||
48 | Include the specified file. | |
49 | ||
50 | <include> ::= | |
51 | ":" "include" | |
52 | ":" <filter-flags> | |
53 | ":" <filter-models> | |
54 | ":" <filename> | |
55 | <nl> | |
56 | ; | |
57 | ||
58 | */ | |
59 | ||
60 | enum { | |
61 | include_filename_field = 4, | |
62 | nr_include_fields, | |
63 | }; | |
64 | ||
65 | ||
66 | ||
67 | /* Options: | |
68 | ||
69 | Valid options are: hi-bit-nr (default 0), insn-bit-size (default | |
70 | 32), insn-specifying-widths (default true), multi-sim (default false). | |
71 | ||
72 | <option> ::= | |
73 | ":" "option" | |
74 | ":" <filter-flags> | |
75 | ":" <filter-models> | |
76 | ":" <option-name> | |
77 | ":" <option-value> | |
78 | <nl> | |
79 | ; | |
80 | ||
81 | <option-name> ::= | |
82 | "insn-bit-size" | |
83 | | "insn-specifying-widths" | |
84 | | "hi-bit-nr" | |
85 | | "flags-filter" | |
86 | | "model-filter" | |
87 | | "multi-sim" | |
88 | | "format-names" | |
89 | ; | |
90 | ||
91 | <option-value> ::= | |
92 | "true" | |
93 | | "false" | |
94 | | <integer> | |
95 | | <list> | |
96 | ; | |
97 | ||
98 | ||
99 | These update the global options structure. */ | |
100 | ||
101 | ||
102 | enum { | |
103 | option_name_field = 4, | |
104 | option_value_field, | |
105 | nr_option_fields, | |
106 | }; | |
107 | ||
108 | ||
109 | ||
110 | /* Macro definitions: | |
111 | ||
112 | <insn-macro> ::= | |
113 | ":" "define" | |
114 | ":" <filter-flags> | |
115 | ":" <filter-models> | |
116 | ":" <name> | |
117 | ":" <arg-list> | |
118 | ":" <expression> | |
119 | <nl> | |
120 | ; | |
121 | ||
122 | <arg-list> ::= | |
123 | [ <name> { "," <arg-list> } ] | |
124 | ; | |
125 | ||
126 | */ | |
127 | ||
128 | ||
129 | enum { | |
130 | macro_name_field = 4, | |
131 | macro_args_field, | |
132 | macro_expr_field, | |
133 | nr_macro_fields, | |
134 | }; | |
135 | ||
136 | ||
137 | ||
138 | /* Functions and internal routins: | |
139 | ||
140 | NB: <filter-models> and <function-models> are equivalent. | |
141 | ||
142 | ||
143 | <function> ::= | |
144 | ":" "function" | |
145 | <function-spec> | |
146 | ; | |
147 | ||
148 | <internal> ::= | |
149 | ":" "internal" | |
150 | <function-spec> | |
151 | ; | |
152 | ||
153 | <format> ::= | |
154 | ":" ( "%s" | ... ) | |
155 | <function-spec> | |
156 | ; | |
157 | ||
158 | <function-model> ::= | |
159 | "*" [ <processor-list> ] | |
160 | ":" | |
161 | <nl> | |
162 | ; | |
163 | ||
164 | <function-spec> ::= | |
165 | ":" <filter-flags> | |
166 | ":" <filter-models> | |
167 | ":" <typedef> | |
168 | ":" <name> | |
169 | [ ":" <parameter-list> ] | |
170 | <nl> | |
171 | [ <function-model> ] | |
172 | <code-block> | |
173 | ; | |
174 | ||
175 | */ | |
176 | ||
177 | enum { | |
178 | function_typedef_field = 4, | |
179 | function_name_field, | |
180 | function_param_field, | |
181 | nr_function_fields, | |
182 | }; | |
183 | ||
184 | enum { | |
185 | function_model_name_field = 0, | |
186 | nr_function_model_fields = 1, | |
187 | }; | |
188 | ||
189 | enum { | |
190 | old_function_typedef_field = 0, | |
191 | old_function_type_field = 2, | |
192 | old_function_name_field = 4, | |
193 | old_function_param_field = 5, | |
194 | nr_old_function_fields = 5, /* parameter-list is optional */ | |
195 | }; | |
196 | ||
197 | ||
198 | typedef struct _function_entry function_entry; | |
199 | struct _function_entry { | |
200 | line_ref *line; | |
201 | filter *flags; | |
202 | filter *models; | |
203 | char *type; | |
204 | char *name; | |
205 | char *param; | |
206 | table_entry *code; | |
207 | int is_internal; | |
208 | function_entry *next; | |
209 | }; | |
210 | ||
211 | ||
212 | typedef void function_entry_handler | |
213 | (lf *file, | |
214 | function_entry *function, | |
215 | void *data); | |
216 | ||
217 | extern void function_entry_traverse | |
218 | (lf *file, | |
219 | function_entry *functions, | |
220 | function_entry_handler *handler, | |
221 | void *data); | |
222 | ||
223 | ||
224 | /* cache-macro: | |
225 | ||
226 | <cache-macro> ::= | |
227 | ":" <macro-type> | |
228 | ":" <filter-flags> | |
229 | ":" <filter-models> | |
230 | ":" <typedef> | |
231 | ":" <name> | |
232 | ":" <field-name> { "," <field-name> } | |
233 | ":" <expression> | |
234 | <nl> | |
235 | ; | |
236 | ||
237 | <cache-macro-type> ::= | |
238 | "scratch" | |
239 | | "cache" | |
240 | | "compute" | |
241 | ; | |
242 | ||
243 | <name> ::= | |
244 | <ident> | |
245 | | <ident> "_is_" <integer> | |
246 | ; | |
247 | ||
248 | A cache entry is defined (for an instruction) when all | |
249 | <field-name>s are present as named opcode fields within the | |
250 | instructions format. | |
251 | ||
252 | SCRATCH and CACHE macros are defined during the cache fill stage | |
253 | while CACHE and COMPUTE macros are defined during the instruction | |
254 | execution stage. | |
255 | ||
256 | */ | |
257 | ||
258 | enum { | |
259 | cache_typedef_field = 4, | |
260 | cache_name_field, | |
261 | cache_original_fields_field, | |
262 | cache_expression_field, | |
263 | nr_cache_fields, | |
264 | }; | |
265 | ||
266 | typedef enum { | |
267 | scratch_value, | |
268 | cache_value, | |
269 | compute_value, | |
270 | } cache_entry_type; | |
271 | ||
272 | typedef struct _cache_entry cache_entry; | |
273 | struct _cache_entry { | |
274 | line_ref *line; | |
275 | filter *flags; | |
276 | filter *models; | |
277 | cache_entry_type entry_type; | |
278 | char *name; | |
279 | filter *original_fields; | |
280 | char *type; | |
281 | char *expression; | |
282 | cache_entry *next; | |
283 | }; | |
284 | ||
285 | ||
286 | ||
287 | /* Model specs: | |
288 | ||
289 | <model-processor> ::= | |
290 | ":" "model" | |
291 | ":" <filter-flags> | |
292 | ":" <filter-models> | |
293 | ":" <processor> | |
294 | ":" <BFD-processor> | |
295 | ":" <function-unit-data> | |
296 | <nl> | |
297 | ; | |
298 | ||
299 | <model-macro> ::= | |
300 | ":" "model-macro" | |
301 | ":" <filter-flags> | |
302 | ":" <filter-models> | |
303 | <nl> | |
304 | <code-block> | |
305 | ; | |
306 | ||
307 | <model-data> ::= | |
308 | ":" "model-data" | |
309 | ":" <filter-flags> | |
310 | ":" <filter-models> | |
311 | <nl> | |
312 | <code-block> | |
313 | ; | |
314 | ||
315 | <model-static> ::= | |
316 | ":" "model-static" | |
317 | <function-spec> | |
318 | ; | |
319 | ||
320 | <model-internal> ::= | |
321 | ":" "model-internal" | |
322 | <function-spec> | |
323 | ; | |
324 | ||
325 | <model-function> ::= | |
326 | ":" "model-internal" | |
327 | <function-spec> | |
328 | ; | |
329 | ||
330 | */ | |
331 | ||
332 | enum { | |
333 | nr_model_macro_fields = 4, | |
334 | nr_model_data_fields = 4, | |
335 | nr_model_static_fields = nr_function_fields, | |
336 | nr_model_internal_fields = nr_function_fields, | |
337 | nr_model_function_fields = nr_function_fields, | |
338 | }; | |
339 | ||
340 | typedef struct _model_data model_data; | |
341 | struct _model_data { | |
342 | line_ref *line; | |
343 | filter *flags; | |
344 | table_entry *entry; | |
345 | table_entry *code; | |
346 | model_data *next; | |
347 | }; | |
348 | ||
349 | enum { | |
350 | model_name_field = 4, | |
351 | model_full_name_field, | |
352 | model_unit_data_field, | |
353 | nr_model_processor_fields, | |
354 | }; | |
355 | ||
356 | typedef struct _model_entry model_entry; | |
357 | struct _model_entry { | |
358 | line_ref *line; | |
359 | filter *flags; | |
360 | char *name; | |
361 | char *full_name; | |
362 | char *unit_data; | |
363 | model_entry *next; | |
364 | }; | |
365 | ||
366 | ||
367 | typedef struct _model_table model_table; | |
368 | struct _model_table { | |
369 | filter *processors; | |
370 | int nr_models; | |
371 | model_entry *models; | |
372 | model_data *macros; | |
373 | model_data *data; | |
374 | function_entry *statics; | |
375 | function_entry *internals; | |
376 | function_entry *functions; | |
377 | }; | |
378 | ||
379 | ||
380 | ||
381 | /* Instruction format: | |
382 | ||
383 | An instruction is composed of a sequence of N bit instruction | |
384 | words. Each word broken into a number of instruction fields. | |
385 | Those fields being constant (ex. an opcode) or variable (register | |
386 | spec). | |
387 | ||
388 | <insn-word> ::= | |
389 | <insn-field> { "," <insn-field> } ; | |
390 | ||
391 | <insn-field> ::= | |
392 | ( <binary-value-implying-width> | |
393 | | <field-name-implying-width> | |
394 | | [ <start-or-width> "." ] <field> | |
395 | ) | |
396 | { [ "!" | "=" ] [ <value> | <field-name> ] } | |
397 | ; | |
398 | ||
399 | <field> ::= | |
400 | { "*" }+ | |
401 | | { "/" }+ | |
402 | | <field-name> | |
403 | | "0x" <hex-value> | |
404 | | "0b" <binary-value> | |
405 | | "0" <octal-value> | |
406 | | <integer-value> ; | |
407 | ||
408 | */ | |
409 | ||
410 | typedef enum _insn_field_cond_type { | |
411 | insn_field_cond_value, | |
412 | insn_field_cond_field, | |
413 | } insn_field_cond_type; | |
414 | typedef enum _insn_field_cond_test { | |
415 | insn_field_cond_eq, | |
416 | insn_field_cond_ne, | |
417 | } insn_field_cond_test; | |
418 | typedef struct _insn_field_cond insn_field_cond; | |
419 | struct _insn_field_cond { | |
420 | insn_field_cond_type type; | |
421 | insn_field_cond_test test; | |
422 | insn_uint value; | |
423 | struct _insn_field_entry *field; | |
424 | char *string; | |
425 | insn_field_cond *next; | |
426 | }; | |
427 | ||
428 | ||
429 | typedef enum _insn_field_type { | |
430 | insn_field_invalid, | |
431 | insn_field_int, | |
432 | insn_field_reserved, | |
433 | insn_field_wild, | |
434 | insn_field_string, | |
435 | } insn_field_type; | |
436 | ||
437 | typedef struct _insn_field_entry insn_field_entry; | |
438 | struct _insn_field_entry { | |
439 | int first; | |
440 | int last; | |
441 | int width; | |
442 | int word_nr; | |
443 | insn_field_type type; | |
444 | insn_uint val_int; | |
445 | char *pos_string; | |
446 | char *val_string; | |
447 | insn_field_cond *conditions; | |
448 | insn_field_entry *next; | |
449 | insn_field_entry *prev; | |
450 | }; | |
451 | ||
452 | typedef struct _insn_bit_entry insn_bit_entry; | |
453 | struct _insn_bit_entry { | |
454 | int value; | |
455 | int mask; | |
456 | insn_field_entry *field; | |
457 | }; | |
458 | ||
459 | ||
460 | ||
461 | ||
462 | typedef struct _insn_entry insn_entry; /* forward */ | |
463 | ||
464 | typedef struct _insn_word_entry insn_word_entry; | |
465 | struct _insn_word_entry { | |
466 | /* list of sub-fields making up the instruction. bit provides | |
467 | faster access to the field data for bit N. */ | |
468 | insn_field_entry *first; | |
469 | insn_field_entry *last; | |
470 | insn_bit_entry *bit[max_insn_bit_size]; | |
471 | /* set of all the string fields */ | |
472 | filter *field_names; | |
473 | /* For multi-word instructions, The Nth word (from zero). */ | |
474 | insn_word_entry *next; | |
475 | }; | |
476 | ||
477 | ||
478 | ||
479 | /* Instruction model: | |
480 | ||
481 | Provides scheduling and other data for the code modeling the | |
482 | instruction unit. | |
483 | ||
484 | <insn-model> ::= | |
485 | "*" [ <processor-list> ] | |
486 | ":" [ <function-unit-data> ] | |
487 | <nl> | |
488 | ; | |
489 | ||
490 | <processor-list> ::= | |
491 | <processor> { "," <processor>" } | |
492 | ; | |
493 | ||
494 | If the <processor-list> is empty, the model is made the default for | |
495 | this instruction. | |
496 | ||
497 | */ | |
498 | ||
499 | enum { | |
500 | insn_model_name_field = 0, | |
501 | insn_model_unit_data_field = 1, | |
502 | nr_insn_model_fields = 1, | |
503 | }; | |
504 | ||
505 | typedef struct _insn_model_entry insn_model_entry; | |
506 | struct _insn_model_entry { | |
507 | line_ref *line; | |
508 | insn_entry *insn; | |
509 | filter *names; | |
510 | char *full_name; | |
511 | char *unit_data; | |
512 | insn_model_entry *next; | |
513 | }; | |
514 | ||
515 | ||
516 | ||
517 | /* Instruction mnemonic: | |
518 | ||
519 | List of assembler mnemonics for the instruction. | |
520 | ||
521 | <insn-mnenonic> ::= | |
522 | "\"" <assembler-mnemonic> "\"" | |
523 | [ ":" <conditional-expression> ] | |
524 | <nl> | |
525 | ; | |
526 | ||
527 | An assembler mnemonic string has the syntax: | |
528 | ||
529 | <assembler-mnemonic> ::= | |
530 | ( [ "%" <format-spec> ] "<" <func> [ "#" <param-list> ] ">" | |
531 | | "%%" | |
532 | | <other-letter> | |
533 | )+ | |
534 | ||
535 | Where, for instance, the text is translated into a printf format | |
536 | and argument pair: | |
537 | ||
538 | "<FUNC>" : "%ld", (long) FUNC | |
539 | "%<FUNC>..." : "%...", FUNC | |
540 | "%s<FUNC>" : "%s", <%s>FUNC (SD_, FUNC) | |
541 | "%s<FUNC#P1,P2>" : "%s", <%s>FUNC (SD_, P1,P2) | |
542 | "%lx<FUNC>" : "%lx", (unsigned long) FUNC | |
543 | "%08lx<FUNC>" : "%08lx", (unsigned long) FUNC | |
544 | ||
545 | And "<%s>FUNC" denotes a function declared using the "%s" record | |
546 | specifier. | |
547 | ||
548 | ||
549 | ||
550 | ; | |
551 | ||
552 | */ | |
553 | ||
554 | enum { | |
555 | insn_mnemonic_format_field = 0, | |
556 | insn_mnemonic_condition_field = 1, | |
557 | nr_insn_mnemonic_fields = 1, | |
558 | }; | |
559 | ||
560 | typedef struct _insn_mnemonic_entry insn_mnemonic_entry; | |
561 | struct _insn_mnemonic_entry { | |
562 | line_ref *line; | |
563 | insn_entry *insn; | |
564 | char *format; | |
565 | char *condition; | |
566 | insn_mnemonic_entry *next; | |
567 | }; | |
568 | ||
569 | ||
570 | ||
571 | /* Instruction: | |
572 | ||
573 | <insn> ::= | |
574 | <insn-word> { "+" <insn-word> } | |
575 | ":" <format-name> | |
576 | ":" <filter-flags> | |
577 | ":" <options> | |
578 | ":" <name> | |
579 | <nl> | |
580 | { <insn-model> } | |
581 | { <insn-mnemonic> } | |
582 | <code-block> | |
583 | ||
584 | */ | |
585 | ||
586 | enum { | |
587 | insn_word_field = 0, | |
588 | insn_format_name_field = 1, | |
589 | insn_filter_flags_field = 2, | |
590 | insn_options_field = 3, | |
591 | insn_name_field = 4, | |
592 | nr_insn_fields = 5, | |
593 | }; | |
594 | ||
595 | ||
596 | /* typedef struct _insn_entry insn_entry; */ | |
597 | struct _insn_entry { | |
598 | line_ref *line; | |
599 | filter *flags; /* filtered by options.filters */ | |
600 | char *format_name; | |
601 | filter *options; | |
602 | char *name; | |
603 | /* the words that make up the instruction. Word provides direct | |
604 | access to word N. Pseudo instructions can be identified by | |
605 | nr_words == 0. */ | |
606 | int nr_words; | |
607 | insn_word_entry *words; | |
608 | insn_word_entry **word; | |
609 | /* a set of all the fields from all the words */ | |
610 | filter *field_names; | |
611 | /* an array of processor models, missing models are NULL! */ | |
612 | int nr_models; | |
613 | insn_model_entry *models; | |
614 | insn_model_entry **model; | |
615 | filter *processors; | |
616 | /* list of assember formats */ | |
617 | int nr_mnemonics; | |
618 | insn_mnemonic_entry *mnemonics; | |
619 | /* code body */ | |
620 | table_entry *code; | |
621 | insn_entry *next; | |
622 | }; | |
623 | ||
624 | ||
625 | /* Instruction table: | |
626 | ||
627 | */ | |
628 | ||
629 | typedef struct _insn_table insn_table; | |
630 | struct _insn_table { | |
631 | cache_entry *caches; | |
632 | int max_nr_words; | |
633 | int nr_insns; | |
634 | insn_entry *insns; | |
635 | function_entry *functions; | |
636 | insn_entry *illegal_insn; | |
637 | model_table *model; | |
638 | filter *options; | |
639 | filter *flags; | |
640 | }; | |
641 | ||
642 | extern insn_table *load_insn_table | |
643 | (char *file_name, | |
644 | cache_entry *cache); | |
645 | ||
646 | typedef void insn_entry_handler | |
647 | (lf *file, | |
648 | insn_table *isa, | |
649 | insn_entry *insn, | |
650 | void *data); | |
651 | ||
652 | extern void insn_table_traverse_insn | |
653 | (lf *file, | |
654 | insn_table *isa, | |
655 | insn_entry_handler *handler, | |
656 | void *data); | |
657 | ||
658 | ||
659 | ||
660 | /* Printing */ | |
661 | ||
662 | extern void print_insn_words | |
663 | (lf *file, | |
664 | insn_entry *insn); | |
665 | ||
666 | ||
667 | ||
668 | /* Debugging */ | |
669 | ||
670 | void | |
671 | dump_insn_field | |
672 | (lf *file, | |
673 | char *prefix, | |
674 | insn_field_entry *field, | |
675 | char *suffix); | |
676 | ||
677 | void | |
678 | dump_insn_word_entry | |
679 | (lf *file, | |
680 | char *prefix, | |
681 | insn_word_entry *word, | |
682 | char *suffix); | |
683 | ||
684 | void | |
685 | dump_insn_entry | |
686 | (lf *file, | |
687 | char *prefix, | |
688 | insn_entry *insn, | |
689 | char *suffix); | |
690 | ||
691 | void | |
692 | dump_cache_entries | |
693 | (lf *file, | |
694 | char *prefix, | |
695 | cache_entry *entry, | |
696 | char *suffix); | |
697 | ||
698 | void | |
699 | dump_insn_table | |
700 | (lf *file, | |
701 | char *prefix, | |
702 | insn_table *isa, | |
703 | char *suffix); |