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