📄 gen.c
字号:
return new_field; }}static voidgen_entry_insert_insn (gen_entry *table, insn_entry * old_insn, int new_word_nr, int new_nr_prefetched_words, int new_opcode_nr, opcode_bits *new_bits){ gen_entry **entry = &table->entries; /* find the new table for this entry */ while ((*entry) != NULL && (*entry)->opcode_nr < new_opcode_nr) { entry = &(*entry)->sibling; } if ((*entry) == NULL || (*entry)->opcode_nr != new_opcode_nr) { /* insert the missing entry */ gen_entry *new_entry = ZALLOC (gen_entry); new_entry->sibling = (*entry); (*entry) = new_entry; table->nr_entries++; /* fill it in */ new_entry->top = table->top; new_entry->opcode_nr = new_opcode_nr; new_entry->word_nr = new_word_nr; new_entry->expanded_bits = new_bits; new_entry->opcode_rule = table->opcode_rule->next; new_entry->parent = table; new_entry->nr_prefetched_words = new_nr_prefetched_words; } /* ASSERT new_bits == cur_entry bits */ ASSERT ((*entry) != NULL && (*entry)->opcode_nr == new_opcode_nr); insn_list_insert (&(*entry)->insns, &(*entry)->nr_insns, old_insn, NULL, /* expanded_bits - only in final list */ NULL, /* opcodes - only in final list */ new_nr_prefetched_words, /* for this table */ report_duplicate_insns);}static voidgen_entry_expand_opcode (gen_entry *table, insn_entry * instruction, int bit_nr, int opcode_nr, opcode_bits *bits){ if (bit_nr > table->opcode->last) { /* Only include the hardwired bit information with an entry IF that entry (and hence its functions) are being duplicated. */ if (options.trace.insn_expansion) { print_gen_entry_path (table->opcode_rule->line, table, notify); notify (NULL, ": insert %d - %s.%s%s\n", opcode_nr, instruction->format_name, instruction->name, (table->opcode_rule-> with_duplicates ? " (duplicated)" : "")); } if (table->opcode_rule->with_duplicates) { gen_entry_insert_insn (table, instruction, table->opcode->word_nr, table->nr_prefetched_words, opcode_nr, bits); } else { gen_entry_insert_insn (table, instruction, table->opcode->word_nr, table->nr_prefetched_words, opcode_nr, NULL); } } else { insn_word_entry *word = instruction->word[table->opcode->word_nr]; insn_field_entry *field = word->bit[bit_nr]->field; 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; switch (field->type) { case insn_field_int: { int val; val = sub_val (field->val_int, field->last, first_pos, last_pos); gen_entry_expand_opcode (table, instruction, last_pos + 1, ((opcode_nr << width) | val), bits); break; } default: { if (field->type == insn_field_reserved) gen_entry_expand_opcode (table, instruction, last_pos + 1, ((opcode_nr << width)), bits); else { int val; int last_val = (table->opcode->is_boolean ? 2 : (1 << width)); for (val = 0; val < last_val; val++) { /* check to see if the value has been precluded (by a conditional) in some way */ int is_precluded; insn_field_cond *condition; for (condition = field->conditions, is_precluded = 0; condition != NULL && !is_precluded; condition = condition->next) { switch (condition->type) { case insn_field_cond_value: { int value = sub_val (condition->value, field->last, first_pos, last_pos); switch (condition->test) { case insn_field_cond_ne: if (value == val) is_precluded = 1; break; case insn_field_cond_eq: if (value != val) is_precluded = 1; break; } break; } case insn_field_cond_field: { int value = -1; opcode_bits *bit; gen_entry *t = NULL; /* Try to find a value for the conditional by looking back through the previously defined bits for one that covers the designated conditional field */ for (bit = bits; bit != NULL; bit = bit->next) { if (bit->field->word_nr == condition->field->word_nr && bit->first <= condition->field->first && bit->last >= condition->field->last) { /* the bit field fully specified the conditional field's value */ value = sub_val (bit->value, bit->last, condition->field-> first, condition->field-> last); } } /* Try to find a value by looking through this and previous tables */ if (bit == NULL) { for (t = table; t->parent != NULL; t = t->parent) { if (t->parent->opcode->word_nr == condition->field->word_nr && t->parent->opcode->first <= condition->field->first && t->parent->opcode->last >= condition->field->last) { /* the table entry fully specified the condition field's value */ /* extract the field's value from the opcode */ value = sub_val (t->opcode_nr, t->parent->opcode->last, condition->field->first, condition->field->last); /* this is a requirement of a conditonal field refering to another field */ ASSERT ((condition->field->first - condition->field->last) == (first_pos - last_pos)); printf ("value=%d, opcode_nr=%d, last=%d, [%d..%d]\n", value, t->opcode_nr, t->parent->opcode->last, condition->field->first, condition->field->last); } } } if (bit == NULL && t == NULL) error (instruction->line, "Conditional `%s' of field `%s' isn't expanded", condition->string, field->val_string); switch (condition->test) { case insn_field_cond_ne: if (value == val) is_precluded = 1; break; case insn_field_cond_eq: if (value != val) is_precluded = 1; break; } break; } } } if (!is_precluded) { /* Only add additional hardwired bit information if the entry is not going to later be combined */ if (table->opcode_rule->with_combine) { gen_entry_expand_opcode (table, instruction, last_pos + 1, ((opcode_nr << width) | val), bits); } else { opcode_bits *new_bits = new_opcode_bits (bits, val, first_pos, last_pos, field, table->opcode); gen_entry_expand_opcode (table, instruction, last_pos + 1, ((opcode_nr << width) | val), new_bits); } } } } } } }}static voidgen_entry_insert_expanding (gen_entry *table, insn_entry * instruction){ gen_entry_expand_opcode (table, instruction, table->opcode->first, 0, table->expanded_bits);}static intinsns_match_format_names (insn_list *insns, filter *format_names){ if (format_names != NULL) { insn_list *i; for (i = insns; i != NULL; i = i->next) { if (i->insn->format_name != NULL && !filter_is_member (format_names, i->insn->format_name)) return 0; } } return 1;}static inttable_matches_path (gen_entry *table, decode_path_list *paths){ if (paths == NULL) return 1; while (paths != NULL) { gen_entry *entry = table; decode_path *path = paths->path; while (1) { if (entry == NULL && path == NULL) return 1; if (entry == NULL || path == NULL) break; if (entry->opcode_nr != path->opcode_nr) break; entry = entry->parent; path = path->parent; } paths = paths->next; } return 0;}static intinsns_match_conditions (insn_list *insns, decode_cond *conditions){ if (conditions != NULL) { insn_list *i; for (i = insns; i != NULL; i = i->next) { decode_cond *cond; for (cond = conditions; cond != NULL; cond = cond->next) { int bit_nr; if (i->insn->nr_words <= cond->word_nr) return 0; for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) { if (!cond->mask[bit_nr]) continue; if (!i->insn->word[cond->word_nr]->bit[bit_nr]->mask) return 0; if ((i->insn->word[cond->word_nr]->bit[bit_nr]->value == cond->value[bit_nr]) == !cond->is_equal) return 0; } } } } return 1;}static intinsns_match_nr_words (insn_list *insns, int nr_words){ insn_list *i; for (i = insns; i != NULL; i = i->next) { if (i->insn->nr_words < nr_words) return 0; } return 1;}static intinsn_list_cmp (insn_list *l, insn_list *r){ while (1) { insn_entry *insn; if (l == NULL && r == NULL) return 0; if (l == NULL) return -1; if (r == NULL) return 1; if (l->insn != r->insn) return -1; /* somewhat arbitrary at present */ /* skip this insn */ insn = l->insn; while (l != NULL && l->insn == insn) l = l->next; while (r != NULL && r->insn == insn) r = r->next; }}static voidgen_entry_expand_insns (gen_entry *table){ decode_table *opcode_rule; ASSERT (table->nr_insns >= 1); /* determine a valid opcode */ for (opcode_rule = table->opcode_rule; opcode_rule != NULL; opcode_rule = opcode_rule->next) { char *discard_reason; if (table->top->model != NULL && opcode_rule->model_names != NULL && !filter_is_member (opcode_rule->model_names, table->top->model->name)) { /* the rule isn't applicable to this processor */ discard_reason = "wrong model"; } else if (table->nr_insns == 1 && opcode_rule->conditions == NULL) { /* for safety, require a pre-codition when attempting to apply a rule to a single instruction */ discard_reason = "need pre-condition when nr-insn == 1"; } else if (table->nr_insns == 1 && !opcode_rule->with_duplicates) { /* Little point in expanding a single instruction when we're not duplicating the semantic functions that this table calls */ discard_reason = "need duplication with nr-insns == 1"; } else if (!insns_match_format_names (table->insns, opcode_rule->format_names)) { discard_reason = "wrong format name"; } else if (!insns_match_nr_words (table->insns, opcode_rule->word_nr + 1)) { discard_reason = "wrong nr words"; } else if (!table_matches_path (table, opcode_rule->paths)) { discard_reason = "path failed"; } else if (!insns_match_conditions (table->insns, opcode_rule->conditions)) { discard_reason = "condition failed"; } else { discard_reason = "no opcode field"; table->opcode = gen_entry_find_opcode_field (table->insns, opcode_rule, table->nr_insns == 1 /*string-only */ ); if (table->opcode != NULL) { table->opcode_rule = opcode_rule; break; } } if (options.trace.rule_rejection) { print_gen_entry_path (opcode_rule->line, table, notify); notify (NULL, ": rule discarded - %s\n", discard_reason); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -