📄 ld-insn.c
字号:
void *data, insn_handler *handler){ insn *instruction; for (instruction = table->insns; instruction != NULL; instruction = instruction->next) { handler(table, file, data, instruction, 0); }}/****************************************************************/typedef enum { field_constant_int = 1, field_constant_slash = 2, field_constant_string = 3} constant_field_types;static intinsn_field_is_constant(insn_field *field, decode_table *rule){ /* field is an integer */ if (field->is_int) return field_constant_int; /* field is `/' and treating that as a constant */ if (field->is_slash && rule->force_slash) return field_constant_slash; /* field, though variable is on the list */ if (field->is_string && rule->force_expansion != NULL) { char *forced_fields = rule->force_expansion; while (*forced_fields != '\0') { int field_len; char *end = strchr(forced_fields, ','); if (end == NULL) field_len = strlen(forced_fields); else field_len = end-forced_fields; if (strncmp(forced_fields, field->val_string, field_len) == 0 && field->val_string[field_len] == '\0') return field_constant_string; forced_fields += field_len; if (*forced_fields == ',') forced_fields++; } } return 0;}static opcode_field *insn_table_find_opcode_field(insn *insns, decode_table *rule, int string_only){ opcode_field *curr_opcode = ZALLOC(opcode_field); insn *entry; ASSERT(rule); curr_opcode->first = insn_bit_size; curr_opcode->last = -1; for (entry = insns; entry != NULL; entry = entry->next) { insn_fields *fields = entry->fields; opcode_field new_opcode; /* find a start point for the opcode field */ new_opcode.first = rule->first; while (new_opcode.first <= rule->last && (!string_only || insn_field_is_constant(fields->bits[new_opcode.first], rule) != field_constant_string) && (string_only || !insn_field_is_constant(fields->bits[new_opcode.first], rule))) new_opcode.first = fields->bits[new_opcode.first]->last + 1; ASSERT(new_opcode.first > rule->last || (string_only && insn_field_is_constant(fields->bits[new_opcode.first], rule) == field_constant_string) || (!string_only && insn_field_is_constant(fields->bits[new_opcode.first], rule))); /* find the end point for the opcode field */ new_opcode.last = rule->last; while (new_opcode.last >= rule->first && (!string_only || insn_field_is_constant(fields->bits[new_opcode.last], rule) != field_constant_string) && (string_only || !insn_field_is_constant(fields->bits[new_opcode.last], rule))) new_opcode.last = fields->bits[new_opcode.last]->first - 1; ASSERT(new_opcode.last < rule->first || (string_only && insn_field_is_constant(fields->bits[new_opcode.last], rule) == field_constant_string) || (!string_only && insn_field_is_constant(fields->bits[new_opcode.last], rule))); /* now see if our current opcode needs expanding */ if (new_opcode.first <= rule->last && curr_opcode->first > new_opcode.first) curr_opcode->first = new_opcode.first; if (new_opcode.last >= rule->first && curr_opcode->last < new_opcode.last) curr_opcode->last = new_opcode.last; } /* was any thing interesting found? */ if (curr_opcode->first > rule->last) { ASSERT(curr_opcode->last < rule->first); return NULL; } ASSERT(curr_opcode->last >= rule->first); ASSERT(curr_opcode->first <= rule->last); /* if something was found, check it includes the forced field range */ if (!string_only && curr_opcode->first > rule->force_first) { curr_opcode->first = rule->force_first; } if (!string_only && curr_opcode->last < rule->force_last) { curr_opcode->last = rule->force_last; } /* handle special case elminating any need to do shift after mask */ if (string_only && rule->force_last == insn_bit_size-1) { curr_opcode->last = insn_bit_size-1; } /* handle any special cases */ switch (rule->type) { case normal_decode_rule: /* let the above apply */ break; case expand_forced_rule: /* expand a limited nr of bits, ignoring the rest */ curr_opcode->first = rule->force_first; curr_opcode->last = rule->force_last; break; case boolean_rule: curr_opcode->is_boolean = 1; curr_opcode->boolean_constant = rule->special_constant; break; default: error("Something is going wrong\n"); } return curr_opcode;}static voidinsn_table_insert_expanded(insn_table *table, insn *old_insn, int new_opcode_nr, insn_bits *new_bits){ insn_table **ptr_to_cur_entry = &table->entries; insn_table *cur_entry = *ptr_to_cur_entry; /* find the new table for this entry */ while (cur_entry != NULL && cur_entry->opcode_nr < new_opcode_nr) { ptr_to_cur_entry = &cur_entry->sibling; cur_entry = *ptr_to_cur_entry; } if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) { insn_table *new_entry = ZALLOC(insn_table); new_entry->opcode_nr = new_opcode_nr; new_entry->expanded_bits = new_bits; new_entry->opcode_rule = table->opcode_rule->next; new_entry->sibling = cur_entry; new_entry->parent = table; *ptr_to_cur_entry = new_entry; cur_entry = new_entry; table->nr_entries++; } /* ASSERT new_bits == cur_entry bits */ ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr); insn_table_insert_insn(cur_entry, old_insn->file_entry, old_insn->fields);}static voidinsn_table_expand_opcode(insn_table *table, insn *instruction, int field_nr, int opcode_nr, insn_bits *bits){ if (field_nr > table->opcode->last) { insn_table_insert_expanded(table, instruction, opcode_nr, bits); } else { insn_field *field = instruction->fields->bits[field_nr]; if (field->is_int || field->is_slash) { ASSERT(field->first >= table->opcode->first && field->last <= table->opcode->last); insn_table_expand_opcode(table, instruction, field->last+1, ((opcode_nr << field->width) + field->val_int), bits); } else { int val; int last_pos = ((field->last < table->opcode->last) ? field->last : table->opcode->last); int first_pos = ((field->first > table->opcode->first) ? field->first : table->opcode->first); int width = last_pos - first_pos + 1; int last_val = (table->opcode->is_boolean ? 2 : (1 << width)); for (val = 0; val < last_val; val++) { insn_bits *new_bits = ZALLOC(insn_bits); new_bits->field = field; new_bits->value = val; new_bits->last = bits; new_bits->opcode = table->opcode; insn_table_expand_opcode(table, instruction, last_pos+1, ((opcode_nr << width) | val), new_bits); } } }}static voidinsn_table_insert_expanding(insn_table *table, insn *entry){ insn_table_expand_opcode(table, entry, table->opcode->first, 0, table->expanded_bits);}extern voidinsn_table_expand_insns(insn_table *table){ ASSERT(table->nr_insn >= 1); /* determine a valid opcode */ while (table->opcode_rule) { /* specials only for single instructions */ if ((table->nr_insn > 1 && table->opcode_rule->special_mask == 0 && table->opcode_rule->type == normal_decode_rule) || (table->nr_insn == 1 && table->opcode_rule->special_mask != 0 && ((table->insns->fields->value & table->opcode_rule->special_mask) == table->opcode_rule->special_value)) || (generate_expanded_instructions && table->opcode_rule->special_mask == 0 && table->opcode_rule->type == normal_decode_rule)) table->opcode = insn_table_find_opcode_field(table->insns, table->opcode_rule, table->nr_insn == 1/*string*/ ); if (table->opcode != NULL) break; table->opcode_rule = table->opcode_rule->next; } /* did we find anything */ if (table->opcode == NULL) { return; } ASSERT(table->opcode != NULL); /* back link what we found to its parent */ if (table->parent != NULL) { ASSERT(table->parent->opcode != NULL); table->opcode->parent = table->parent->opcode; } /* expand the raw instructions according to the opcode */ { insn *entry; for (entry = table->insns; entry != NULL; entry = entry->next) { insn_table_insert_expanding(table, entry); } } /* and do the same for the sub entries */ { insn_table *entry; for (entry = table->entries; entry != NULL; entry = entry->sibling) { insn_table_expand_insns(entry); } }}#ifdef MAINstatic voiddump_insn_field(insn_field *field, int indent){ printf("(insn_field*)0x%x\n", (unsigned)field); dumpf(indent, "(first %d)\n", field->first); dumpf(indent, "(last %d)\n", field->last); dumpf(indent, "(width %d)\n", field->width); if (field->is_int) dumpf(indent, "(is_int %d)\n", field->val_int); if (field->is_slash) dumpf(indent, "(is_slash)\n"); if (field->is_string) dumpf(indent, "(is_string `%s')\n", field->val_string); dumpf(indent, "(next 0x%x)\n", field->next); dumpf(indent, "(prev 0x%x)\n", field->prev); }static voiddump_insn_fields(insn_fields *fields, int indent){ int i; printf("(insn_fields*)%p\n", fields); dumpf(indent, "(first 0x%x)\n", fields->first); dumpf(indent, "(last 0x%x)\n", fields->last); dumpf(indent, "(value 0x%x)\n", fields->value); for (i = 0; i < insn_bit_size; i++) { dumpf(indent, "(bits[%d] ", i, fields->bits[i]); dump_insn_field(fields->bits[i], indent+1); dumpf(indent, " )\n"); }}static voiddump_opcode_field(opcode_field *field, int indent, int levels){ printf("(opcode_field*)%p\n", field); if (levels && field != NULL) { dumpf(indent, "(first %d)\n", field->first); dumpf(indent, "(last %d)\n", field->last); dumpf(indent, "(is_boolean %d)\n", field->is_boolean); dumpf(indent, "(parent "); dump_opcode_field(field->parent, indent, levels-1); }}static voiddump_insn_bits(insn_bits *bits, int indent, int levels){ printf("(insn_bits*)%p\n", bits); if (levels && bits != NULL) { dumpf(indent, "(value %d)\n", bits->value); dumpf(indent, "(opcode "); dump_opcode_field(bits->opcode, indent+1, 0); dumpf(indent, " )\n"); dumpf(indent, "(field "); dump_insn_field(bits->field, indent+1); dumpf(indent, " )\n"); dumpf(indent, "(last "); dump_insn_bits(bits->last, indent+1, levels-1); }}static voiddump_insn(insn *entry, int indent, int levels){ printf("(insn*)%p\n", entry); if (levels && entry != NULL) { dumpf(indent, "(file_entry "); dump_table_entry(entry->file_entry, indent+1); dumpf(indent, " )\n"); dumpf(indent, "(fields "); dump_insn_fields(entry->fields, indent+1); dumpf(indent, " )\n"); dumpf(indent, "(next "); dump_insn(entry->next, indent+1, levels-1); dumpf(indent, " )\n"); }}static voiddump_insn_table(insn_table *table, int indent, int levels){ printf("(insn_table*)%p\n", table); if (levels && table != NULL) { dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr); dumpf(indent, "(expanded_bits "); dump_insn_bits(table->expanded_bits, indent+1, -1); dumpf(indent, " )\n"); dumpf(indent, "(int nr_insn %d)\n", table->nr_insn); dumpf(indent, "(insns "); dump_insn(table->insns, indent+1, table->nr_insn); dumpf(indent, " )\n"); dumpf(indent, "(opcode_rule "); dump_decode_rule(table->opcode_rule, indent+1); dumpf(indent, " )\n"); dumpf(indent, "(opcode "); dump_opcode_field(table->opcode, indent+1, 1); dumpf(indent, " )\n"); dumpf(indent, "(nr_entries %d)\n", table->entries); dumpf(indent, "(entries "); dump_insn_table(table->entries, indent+1, table->nr_entries); dumpf(indent, " )\n"); dumpf(indent, "(sibling ", table->sibling); dump_insn_table(table->sibling, indent+1, levels-1); dumpf(indent, " )\n"); dumpf(indent, "(parent ", table->parent); dump_insn_table(table->parent, indent+1, 0); dumpf(indent, " )\n"); }}int insn_bit_size = max_insn_bit_size;int hi_bit_nr;int generate_expanded_instructions;intmain(int argc, char **argv){ filter *filters = NULL; decode_table *decode_rules = NULL; insn_table *instructions = NULL; cache_table *cache_rules = NULL; if (argc != 5) error("Usage: insn <filter> <hi-bit-nr> <decode-table> <insn-table>\n"); filters = new_filter(argv[1], filters); hi_bit_nr = a2i(argv[2]); ASSERT(hi_bit_nr < insn_bit_size); decode_rules = load_decode_table(argv[3], hi_bit_nr); instructions = load_insn_table(argv[4], decode_rules, filters, NULL, &cache_rules); insn_table_expand_insns(instructions); dump_insn_table(instructions, 0, -1); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -