📄 gen.c
字号:
} (*cur_insn_ptr) = new_insn; } *nr_insns += 1; return (*cur_insn_ptr);}extern voidgen_entry_traverse_tree (lf *file, gen_entry *table, int depth, gen_entry_handler * start, gen_entry_handler * leaf, gen_entry_handler * end, void *data){ gen_entry *entry; ASSERT (table !=NULL); ASSERT (table->opcode != NULL); ASSERT (table->nr_entries > 0); ASSERT (table->entries != 0); /* prefix */ if (start != NULL && depth >= 0) { start (file, table, depth, data); } /* infix leaves */ for (entry = table->entries; entry != NULL; entry = entry->sibling) { if (entry->entries != NULL && depth != 0) { gen_entry_traverse_tree (file, entry, depth + 1, start, leaf, end, data); } else if (depth >= 0) { if (leaf != NULL) { leaf (file, entry, depth, data); } } } /* postfix */ if (end != NULL && depth >= 0) { end (file, table, depth, data); }}/* create a list element containing a single gen_table entry */static gen_list *make_table (insn_table *isa, decode_table *rules, model_entry *model){ insn_entry *insn; gen_list *entry = ZALLOC (gen_list); entry->table = ZALLOC (gen_entry); entry->table->top = entry; entry->model = model; entry->isa = isa; for (insn = isa->insns; insn != NULL; insn = insn->next) { if (model == NULL || insn->processors == NULL || filter_is_member (insn->processors, model->name)) { insn_list_insert (&entry->table->insns, &entry->table->nr_insns, insn, NULL, /* expanded_bits - none yet */ NULL, /* opcodes - none yet */ 0, /* nr_prefetched_words - none yet */ report_duplicate_insns); } } entry->table->opcode_rule = rules; return entry;}gen_table *make_gen_tables (insn_table *isa, decode_table *rules){ gen_table *gen = ZALLOC (gen_table); gen->isa = isa; gen->rules = rules; if (options.gen.multi_sim) { gen_list **last = &gen->tables; model_entry *model; filter *processors; if (options.model_filter != NULL) processors = options.model_filter; else processors = isa->model->processors; for (model = isa->model->models; model != NULL; model = model->next) { if (filter_is_member (processors, model->name)) { *last = make_table (isa, rules, model); last = &(*last)->next; } } } else { gen->tables = make_table (isa, rules, NULL); } return gen;}/****************************************************************/#if 0typedef enum{ field_is_not_constant = 0, field_constant_int = 1, field_constant_reserved = 2, field_constant_string = 3}constant_field_types;static constant_field_typesinsn_field_is_constant (insn_field * field, decode_table *rule){ switch (field->type) { case insn_field_int: /* field is an integer */ return field_constant_int; case insn_field_reserved: /* field is `/' and treating that as a constant */ if (rule->with_zero_reserved) return field_constant_reserved; else return field_is_not_constant; case insn_field_wild: return field_is_not_constant; /* never constant */ case insn_field_string: /* field, though variable, is on the list of forced constants */ if (filter_is_member (rule->constant_field_names, field->val_string)) return field_constant_string; else return field_is_not_constant; } ERROR ("Internal error"); return field_is_not_constant;}#endif/****************************************************************//* Is the bit, according to the decode rule, identical across all the instructions? */static intinsns_bit_useless (insn_list *insns, decode_table *rule, int bit_nr){ insn_list *entry; int value = -1; int is_useless = 1; /* cleared if something actually found */ /* check the instructions for some constant value in at least one of the bit fields */ for (entry = insns; entry != NULL; entry = entry->next) { insn_word_entry *word = entry->insn->word[rule->word_nr]; insn_bit_entry *bit = word->bit[bit_nr]; switch (bit->field->type) { case insn_field_invalid: ASSERT (0); break; case insn_field_wild: case insn_field_reserved: /* neither useless or useful - ignore */ break; case insn_field_int: switch (rule->search) { case decode_find_strings: /* an integer isn't a string */ return 1; case decode_find_constants: case decode_find_mixed: /* an integer is useful if its value isn't the same between all instructions. The first time through the value is saved, the second time through (if the values differ) it is marked as useful. */ if (value < 0) value = bit->value; else if (value != bit->value) is_useless = 0; break; } break; case insn_field_string: switch (rule->search) { case decode_find_strings: /* at least one string, keep checking */ is_useless = 0; break; case decode_find_constants: case decode_find_mixed: if (filter_is_member (rule->constant_field_names, bit->field->val_string)) /* a string field forced to constant? */ is_useless = 0; else if (rule->search == decode_find_constants) /* the string field isn't constant */ return 1; break; } } } /* Given only one constant value has been found, check through all the instructions to see if at least one conditional makes it usefull */ if (value >= 0 && is_useless) { for (entry = insns; entry != NULL; entry = entry->next) { insn_word_entry *word = entry->insn->word[rule->word_nr]; insn_bit_entry *bit = word->bit[bit_nr]; switch (bit->field->type) { case insn_field_invalid: ASSERT (0); break; case insn_field_wild: case insn_field_reserved: case insn_field_int: /* already processed */ break; case insn_field_string: switch (rule->search) { case decode_find_strings: case decode_find_constants: /* already processed */ break; case decode_find_mixed: /* string field with conditions. If this condition eliminates the value then the compare is useful */ if (bit->field->conditions != NULL) { insn_field_cond *condition; int shift = bit->field->last - bit_nr; for (condition = bit->field->conditions; condition != NULL; condition = condition->next) { switch (condition->type) { case insn_field_cond_value: switch (condition->test) { case insn_field_cond_ne: if (((condition->value >> shift) & 1) == (unsigned) value) /* conditional field excludes the current value */ is_useless = 0; break; case insn_field_cond_eq: if (((condition->value >> shift) & 1) != (unsigned) value) /* conditional field requires the current value */ is_useless = 0; break; } break; case insn_field_cond_field: /* are these handled separatly? */ break; } } } } } } } return is_useless;}/* go through a gen-table's list of instruction formats looking for a range of bits that meet the decode table RULEs requirements */static opcode_field *gen_entry_find_opcode_field (insn_list *insns, decode_table *rule, int string_only){ opcode_field curr_opcode; ASSERT (rule != NULL); memset (&curr_opcode, 0, sizeof (curr_opcode)); curr_opcode.word_nr = rule->word_nr; curr_opcode.first = rule->first; curr_opcode.last = rule->last; /* Try to reduce the size of first..last in accordance with the decode rules */ while (curr_opcode.first <= rule->last) { if (insns_bit_useless (insns, rule, curr_opcode.first)) curr_opcode.first++; else break; } while (curr_opcode.last >= rule->first) { if (insns_bit_useless (insns, rule, curr_opcode.last)) curr_opcode.last--; else break; }#if 0 for (entry = insns; entry != NULL; entry = entry->next) { insn_word_entry *fields = entry->insn->word[rule->word_nr]; opcode_field new_opcode; ASSERT (fields != NULL); /* 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->bit[new_opcode.first], rule) != field_constant_string)) && (string_only || (insn_field_is_constant (fields-> bit[new_opcode.first], rule) == field_is_not_constant))) { int new_first = fields->bit[new_opcode.first]->last + 1; ASSERT (new_first > new_opcode.first); new_opcode.first = new_first; } ASSERT (new_opcode.first > rule->last || (string_only && insn_field_is_constant (fields->bit[new_opcode.first], rule) == field_constant_string) || (!string_only && insn_field_is_constant (fields->bit[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->bit[new_opcode.last], rule) != field_constant_string) && (string_only || !insn_field_is_constant (fields->bit[new_opcode.last], rule))) { int new_last = fields->bit[new_opcode.last]->first - 1; ASSERT (new_last < new_opcode.last); new_opcode.last = new_last; } ASSERT (new_opcode.last < rule->first || (string_only && insn_field_is_constant (fields->bit[new_opcode.last], rule) == field_constant_string) || (!string_only && insn_field_is_constant (fields->bit[new_opcode.last], rule))); /* now see if our current opcode needs expanding to include the interesting fields within this instruction */ 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; }#endif /* did the final opcode field end up being empty? */ if (curr_opcode.first > curr_opcode.last) { return NULL; } ASSERT (curr_opcode.last >= rule->first); ASSERT (curr_opcode.first <= rule->last); ASSERT (curr_opcode.first <= curr_opcode.last); /* Ensure that, for the non string only case, the opcode includes the range forced_first .. forced_last */ 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; } /* For the string only case, force just the lower bound (so that the shift can be eliminated) */ if (string_only && rule->force_last == options.insn_bit_size - 1) { curr_opcode.last = options.insn_bit_size - 1; } /* handle any special cases */ switch (rule->type) { case normal_decode_rule: /* let the above apply */ curr_opcode.nr_opcodes = (1 << (curr_opcode.last - curr_opcode.first + 1)); break; case boolean_rule: curr_opcode.is_boolean = 1; curr_opcode.boolean_constant = rule->constant; curr_opcode.nr_opcodes = 2; break; } { opcode_field *new_field = ZALLOC (opcode_field); memcpy (new_field, &curr_opcode, sizeof (opcode_field));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -