📄 gen.c
字号:
} /* did we find anything */ if (opcode_rule == NULL) { /* the decode table failed, this set of instructions haven't been uniquely identified */ if (table->nr_insns > 1) { print_gen_entry_insns (table, warning, "was not uniquely decoded", "decodes to the same entry"); error (NULL, ""); } return; } /* Determine the number of words that must have been prefetched for this table to function */ if (table->parent == NULL) table->nr_prefetched_words = table->opcode_rule->word_nr + 1; else if (table->opcode_rule->word_nr + 1 > table->parent->nr_prefetched_words) table->nr_prefetched_words = table->opcode_rule->word_nr + 1; else table->nr_prefetched_words = table->parent->nr_prefetched_words; /* back link what we found to its parent */ if (table->parent != NULL) { ASSERT (table->parent->opcode != NULL); table->opcode->parent = table->parent->opcode; } /* report the rule being used to expand the instructions */ if (options.trace.rule_selection) { print_gen_entry_path (table->opcode_rule->line, table, notify); notify (NULL, ": decode - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d\n", table->opcode->word_nr, i2target (options.hi_bit_nr, table->opcode->first), i2target (options.hi_bit_nr, table->opcode->last), i2target (options.hi_bit_nr, table->opcode_rule->first), i2target (options.hi_bit_nr, table->opcode_rule->last), table->opcode->nr_opcodes, table->nr_entries); } /* expand the raw instructions according to the opcode */ { insn_list *entry; for (entry = table->insns; entry != NULL; entry = entry->next) { if (options.trace.insn_expansion) { print_gen_entry_path (table->opcode_rule->line, table, notify); notify (NULL, ": expand - %s.%s\n", entry->insn->format_name, entry->insn->name); } gen_entry_insert_expanding (table, entry->insn); } } /* dump the results */ if (options.trace.entries) { gen_entry *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { insn_list *l; print_gen_entry_path (table->opcode_rule->line, entry, notify); notify (NULL, ": %d - entries %d -", entry->opcode_nr, entry->nr_insns); for (l = entry->insns; l != NULL; l = l->next) notify (NULL, " %s.%s", l->insn->format_name, l->insn->name); notify (NULL, "\n"); } } /* perform a combine pass if needed */ if (table->opcode_rule->with_combine) { gen_entry *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { if (entry->combined_parent == NULL) { gen_entry **last = &entry->combined_next; gen_entry *alt; for (alt = entry->sibling; alt != NULL; alt = alt->sibling) { if (alt->combined_parent == NULL && insn_list_cmp (entry->insns, alt->insns) == 0) { alt->combined_parent = entry; *last = alt; last = &alt->combined_next; } } } } if (options.trace.combine) { int nr_unique = 0; gen_entry *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { if (entry->combined_parent == NULL) { insn_list *l; gen_entry *duplicate; nr_unique++; print_gen_entry_path (table->opcode_rule->line, entry, notify); for (duplicate = entry->combined_next; duplicate != NULL; duplicate = duplicate->combined_next) { notify (NULL, "+%d", duplicate->opcode_nr); } notify (NULL, ": entries %d -", entry->nr_insns); for (l = entry->insns; l != NULL; l = l->next) { notify (NULL, " %s.%s", l->insn->format_name, l->insn->name); } notify (NULL, "\n"); } } print_gen_entry_path (table->opcode_rule->line, table, notify); notify (NULL, ": combine - word %d, bits [%d..%d] in [%d..%d], opcodes %d, entries %d, unique %d\n", table->opcode->word_nr, i2target (options.hi_bit_nr, table->opcode->first), i2target (options.hi_bit_nr, table->opcode->last), i2target (options.hi_bit_nr, table->opcode_rule->first), i2target (options.hi_bit_nr, table->opcode_rule->last), table->opcode->nr_opcodes, table->nr_entries, nr_unique); } } /* Check that the rule did more than re-arange the order of the instructions */ { gen_entry *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { if (entry->combined_parent == NULL) { if (insn_list_cmp (table->insns, entry->insns) == 0) { print_gen_entry_path (table->opcode_rule->line, table, warning); warning (NULL, ": Applying rule just copied all instructions\n"); print_gen_entry_insns (entry, warning, "Copied", NULL); error (NULL, ""); } } } } /* if some form of expanded table, fill in the missing dots */ switch (table->opcode_rule->gen) { case padded_switch_gen: case array_gen: case goto_switch_gen: if (!table->opcode->is_boolean) { gen_entry **entry = &table->entries; gen_entry *illegals = NULL; gen_entry **last_illegal = &illegals; int opcode_nr = 0; while (opcode_nr < table->opcode->nr_opcodes) { if ((*entry) == NULL || (*entry)->opcode_nr != opcode_nr) { /* missing - insert it under our feet at *entry */ gen_entry_insert_insn (table, table->top->isa->illegal_insn, table->opcode->word_nr, 0, /* nr_prefetched_words == 0 for invalid */ opcode_nr, NULL); ASSERT ((*entry) != NULL); ASSERT ((*entry)->opcode_nr == opcode_nr); (*last_illegal) = *entry; (*last_illegal)->combined_parent = illegals; last_illegal = &(*last_illegal)->combined_next; } entry = &(*entry)->sibling; opcode_nr++; } /* oops, will have pointed the first illegal insn back to its self. Fix this */ if (illegals != NULL) illegals->combined_parent = NULL; } break; case switch_gen: case invalid_gen: /* ignore */ break; } /* and do the same for the newly created sub entries but *only* expand entries that haven't been combined. */ { gen_entry *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { if (entry->combined_parent == NULL) { gen_entry_expand_insns (entry); } } }}voidgen_tables_expand_insns (gen_table *gen){ gen_list *entry; for (entry = gen->tables; entry != NULL; entry = entry->next) { gen_entry_expand_insns (entry->table); }}/* create a list of all the semantic functions that need to be generated. Eliminate any duplicates. Verify that the decode stage worked. */static voidmake_gen_semantics_list (lf *file, gen_entry *entry, int depth, void *data){ gen_table *gen = (gen_table *) data; insn_list *insn; /* Not interested in an entrie that have been combined into some other entry at the same level */ if (entry->combined_parent != NULL) return; /* a leaf should contain exactly one instruction. If not the decode stage failed. */ ASSERT (entry->nr_insns == 1); /* Enter this instruction into the list of semantic functions. */ insn = insn_list_insert (&gen->semantics, &gen->nr_semantics, entry->insns->insn, entry->expanded_bits, entry->parent->opcode, entry->insns->nr_prefetched_words, merge_duplicate_insns); /* point the table entry at the real semantic function */ ASSERT (insn != NULL); entry->insns->semantic = insn;}voidgen_tables_expand_semantics (gen_table *gen){ gen_list *entry; for (entry = gen->tables; entry != NULL; entry = entry->next) { gen_entry_traverse_tree (NULL, entry->table, 1, /* depth */ NULL, /* start-handler */ make_gen_semantics_list, /* leaf-handler */ NULL, /* end-handler */ gen); /* data */ }}#ifdef MAINstatic voiddump_opcode_field (lf *file, char *prefix, opcode_field *field, char *suffix, int levels){ lf_printf (file, "%s(opcode_field *) 0x%lx", prefix, (long) field); if (levels && field != NULL) { lf_indent (file, +1); lf_printf (file, "\n(first %d)", field->first); lf_printf (file, "\n(last %d)", field->last); lf_printf (file, "\n(nr_opcodes %d)", field->nr_opcodes); lf_printf (file, "\n(is_boolean %d)", field->is_boolean); lf_printf (file, "\n(boolean_constant %d)", field->boolean_constant); dump_opcode_field (file, "\n(parent ", field->parent, ")", levels - 1); lf_indent (file, -1); } lf_printf (file, "%s", suffix);}static voiddump_opcode_bits (lf *file, char *prefix, opcode_bits *bits, char *suffix, int levels){ lf_printf (file, "%s(opcode_bits *) 0x%lx", prefix, (long) bits); if (levels && bits != NULL) { lf_indent (file, +1); lf_printf (file, "\n(value %d)", bits->value); dump_opcode_field (file, "\n(opcode ", bits->opcode, ")", 0); dump_insn_field (file, "\n(field ", bits->field, ")"); dump_opcode_bits (file, "\n(next ", bits->next, ")", levels - 1); lf_indent (file, -1); } lf_printf (file, "%s", suffix);}static voiddump_insn_list (lf *file, char *prefix, insn_list *entry, char *suffix){ lf_printf (file, "%s(insn_list *) 0x%lx", prefix, (long) entry); if (entry != NULL) { lf_indent (file, +1); dump_insn_entry (file, "\n(insn ", entry->insn, ")"); lf_printf (file, "\n(next 0x%lx)", (long) entry->next); lf_indent (file, -1); } lf_printf (file, "%s", suffix);}static voiddump_insn_word_entry_list_entries (lf *file, char *prefix, insn_list *entry, char *suffix){ lf_printf (file, "%s", prefix); while (entry != NULL) { dump_insn_list (file, "\n(", entry, ")"); entry = entry->next; } lf_printf (file, "%s", suffix);}static voiddump_gen_entry (lf *file, char *prefix, gen_entry *table, char *suffix, int levels){ lf_printf (file, "%s(gen_entry *) 0x%lx", prefix, (long) table); if (levels && table !=NULL) { lf_indent (file, +1); lf_printf (file, "\n(opcode_nr %d)", table->opcode_nr); lf_printf (file, "\n(word_nr %d)", table->word_nr); dump_opcode_bits (file, "\n(expanded_bits ", table->expanded_bits, ")", -1); lf_printf (file, "\n(nr_insns %d)", table->nr_insns); dump_insn_word_entry_list_entries (file, "\n(insns ", table->insns, ")"); dump_decode_rule (file, "\n(opcode_rule ", table->opcode_rule, ")"); dump_opcode_field (file, "\n(opcode ", table->opcode, ")", 0); lf_printf (file, "\n(nr_entries %d)", table->nr_entries); dump_gen_entry (file, "\n(entries ", table->entries, ")", table->nr_entries); dump_gen_entry (file, "\n(sibling ", table->sibling, ")", levels - 1); dump_gen_entry (file, "\n(parent ", table->parent, ")", 0); lf_indent (file, -1); } lf_printf (file, "%s", suffix);}static voiddump_gen_list (lf *file, char *prefix, gen_list *entry, char *suffix, int levels){ while (entry != NULL) { lf_printf (file, "%s(gen_list *) 0x%lx", prefix, (long) entry); dump_gen_entry (file, "\n(", entry->table, ")", levels); lf_printf (file, "\n(next (gen_list *) 0x%lx)", (long) entry->next); lf_printf (file, "%s", suffix); }}static voiddump_gen_table (lf *file, char *prefix, gen_table *gen, char *suffix, int levels){ lf_printf (file, "%s(gen_table *) 0x%lx", prefix, (long) gen); lf_printf (file, "\n(isa (insn_table *) 0x%lx)", (long) gen->isa); lf_printf (file, "\n(rules (decode_table *) 0x%lx)", (long) gen->rules); dump_gen_list (file, "\n(", gen->tables, ")", levels); lf_printf (file, "%s", suffix);}igen_options options;intmain (int argc, char **argv){ decode_table *decode_rules; insn_table *instructions; gen_table *gen; lf *l; if (argc != 7) error (NULL, "Usage: insn <filter-in> <hi-bit-nr> <insn-bit-size> <widths> <decode-table> <insn-table>\n"); INIT_OPTIONS (options); filter_parse (&options.flags_filter, argv[1]); options.hi_bit_nr = a2i (argv[2]); options.insn_bit_size = a2i (argv[3]); options.insn_specifying_widths = a2i (argv[4]); ASSERT (options.hi_bit_nr < options.insn_bit_size); instructions = load_insn_table (argv[6], NULL); decode_rules = load_decode_table (argv[5]); gen = make_gen_tables (instructions, decode_rules); gen_tables_expand_insns (gen); l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn"); dump_gen_table (l, "(", gen, ")\n", -1); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -