static void print_icache_extraction(lf *file, insn *instruction, const char *entry_name, const char *entry_type, const char *entry_expression, const char *original_name, const char *file_name, int line_nr, insn_field *cur_field, insn_bits *bits, icache_decl_type what_to_declare, icache_body_type what_to_do, const char *reason) { const char *expression; ASSERT(entry_name != NULL); /* Define a storage area for the cache element */ if (what_to_declare == undef_variables) { /* We've finished with the value - destory it */ lf_indent_suppress(file); lf_printf(file, "#undef %s\n", entry_name); return; } else if (what_to_declare == define_variables) { lf_indent_suppress(file); lf_printf(file, "#define %s ", entry_name); } else { if (file_name != NULL) lf_print__external_reference(file, line_nr, file_name); lf_printf(file, "%s const %s UNUSED = ", entry_type == NULL ? "unsigned" : entry_type, entry_name); } /* define a value for that storage area as determined by what is in the cache */ if (bits != NULL && strcmp(entry_name, cur_field->val_string) == 0 && ((bits->opcode->is_boolean && bits->value == 0) || (!bits->opcode->is_boolean))) { /* The simple field has been made constant (as a result of expanding instructions or similar). Remember that for a boolean field, value is either 0 (implying the required boolean_constant) or nonzero (implying some other value and handled later below) - Define the variable accordingly */ expression = "constant field"; ASSERT(bits->field == cur_field); ASSERT(entry_type == NULL); if (bits->opcode->is_boolean) lf_printf(file, "%d", bits->opcode->boolean_constant); else if (bits->opcode->last < bits->field->last) lf_printf(file, "%d", bits->value << (bits->field->last - bits->opcode->last)); else lf_printf(file, "%d", bits->value); } else if (bits != NULL && original_name != NULL && strncmp(entry_name, original_name, strlen(original_name)) == 0 && strncmp(entry_name + strlen(original_name), "_is_", strlen("_is_")) == 0 && ((bits->opcode->is_boolean && (atol(entry_name + strlen(original_name) + strlen("_is_")) == bits->opcode->boolean_constant)) || (!bits->opcode->is_boolean))) { expression = "constant compare"; /* An entry, derived from ORIGINAL_NAME, is testing to see of the ORIGINAL_NAME has a specific constant value. That value matching a boolean or constant field */ if (bits->opcode->is_boolean) lf_printf(file, "%d /* %s == %d */", bits->value == 0, original_name, bits->opcode->boolean_constant); else if (bits->opcode->last < bits->field->last) lf_printf(file, "%d /* %s == %d */", (atol(entry_name + strlen(original_name) + strlen("_is_")) == (bits->value << (bits->field->last - bits->opcode->last))), original_name, (bits->value << (bits->field->last - bits->opcode->last))); else lf_printf(file, "%d /* %s == %d */", (atol(entry_name + strlen(original_name) + strlen("_is_")) == bits->value), original_name, bits->value); } else { /* put the field in the local variable, possibly also enter it into the cache */ expression = "extraction"; /* handle the cache */ if ((what_to_do & get_values_from_icache) || (what_to_do & put_values_in_icache)) { lf_printf(file, "cache_entry->crack.%s.%s", instruction->file_entry->fields[insn_form], entry_name); if (what_to_do & put_values_in_icache) /* also put it in the cache? */ lf_printf(file, " = "); } if ((what_to_do & put_values_in_icache) || what_to_do == do_not_use_icache) { if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0) lf_printf(file, "EXTRACTED32(instruction, %d, %d)", i2target(hi_bit_nr, cur_field->first), i2target(hi_bit_nr, cur_field->last)); else if (entry_expression != NULL) lf_printf(file, "%s", entry_expression); else lf_printf(file, "eval_%s", entry_name); } } if (!((what_to_declare == define_variables) || (what_to_declare == undef_variables))) lf_printf(file, ";"); if (reason != NULL) lf_printf(file, " /* %s - %s */", reason, expression); lf_printf(file, "\n"); }
static void print_icache_extraction (lf *file, const char *format_name, cache_entry_type cache_type, const char *entry_name, const char *entry_type, const char *entry_expression, char *single_insn_field, line_ref *line, insn_field_entry *cur_field, opcode_bits *expanded_bits, icache_decl_type what_to_declare, icache_body_type what_to_do) { const char *expression; opcode_bits *bits; char *reason; ASSERT (format_name != NULL); ASSERT (entry_name != NULL); /* figure out exactly what should be going on here */ switch (cache_type) { case scratch_value: if ((what_to_do & put_values_in_icache) || what_to_do == do_not_use_icache) { reason = "scratch"; what_to_do = do_not_use_icache; } else return; break; case compute_value: if ((what_to_do & get_values_from_icache) || what_to_do == do_not_use_icache) { reason = "compute"; what_to_do = do_not_use_icache; } else return; break; case cache_value: if ((what_to_declare != undef_variables) || !(what_to_do & put_values_in_icache)) { reason = "cache"; what_to_declare = ((what_to_do & put_values_in_icache) ? declare_variables : what_to_declare); } else return; break; default: abort (); /* Bad switch. */ } /* For the type, default to a simple unsigned */ if (entry_type == NULL || strlen (entry_type) == 0) entry_type = "unsigned"; /* look through the set of expanded sub fields to see if this field has been given a constant value */ for (bits = expanded_bits; bits != NULL; bits = bits->next) { if (bits->field == cur_field) break; } /* Define a storage area for the cache element */ switch (what_to_declare) { case undef_variables: /* We've finished with the #define value - destory it */ lf_indent_suppress (file); lf_printf (file, "#undef %s\n", entry_name); return; case define_variables: /* Using direct access for this entry, clear any prior definition, then define it */ lf_indent_suppress (file); lf_printf (file, "#undef %s\n", entry_name); /* Don't type cast pointer types! */ lf_indent_suppress (file); if (strchr (entry_type, '*') != NULL) lf_printf (file, "#define %s (", entry_name); else lf_printf (file, "#define %s ((%s) ", entry_name, entry_type); break; case declare_variables: /* using variables to define the value */ if (line != NULL) lf_print__line_ref (file, line); lf_printf (file, "%s const %s UNUSED = ", entry_type, entry_name); break; } /* define a value for that storage area as determined by what is in the cache */ if (bits != NULL && single_insn_field != NULL && strcmp (entry_name, single_insn_field) == 0 && strcmp (entry_name, cur_field->val_string) == 0 && ((bits->opcode->is_boolean && bits->value == 0) || (!bits->opcode->is_boolean))) { /* The cache rule is specifying what to do with a simple instruction field. Because of instruction expansion, the field is either a constant value or equal to the specified constant (boolean comparison). (The latter indicated by bits->value == 0). The case of a field not being equal to the specified boolean value is handled later. */ expression = "constant field"; ASSERT (bits->field == cur_field); if (bits->opcode->is_boolean) { ASSERT (bits->value == 0); lf_printf (file, "%d", bits->opcode->boolean_constant); } else if (bits->opcode->last < bits->field->last) { lf_printf (file, "%d", bits->value << (bits->field->last - bits->opcode->last)); } else { lf_printf (file, "%d", bits->value); } } else if (bits != NULL && single_insn_field != NULL && strncmp (entry_name, single_insn_field, strlen (single_insn_field)) == 0 && strncmp (entry_name + strlen (single_insn_field), "_is_", strlen ("_is_")) == 0 && ((bits->opcode->is_boolean && ((unsigned) atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == bits->opcode->boolean_constant)) || (!bits->opcode->is_boolean))) { /* The cache rule defines an entry for the comparison between a single instruction field and a constant. The value of the comparison in someway matches that of the opcode field that was made constant through expansion. */ expression = "constant compare"; if (bits->opcode->is_boolean) { lf_printf (file, "%d /* %s == %d */", bits->value == 0, single_insn_field, bits->opcode->boolean_constant); } else if (bits->opcode->last < bits->field->last) { lf_printf (file, "%d /* %s == %d */", (atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == (bits-> value << (bits->field->last - bits->opcode->last))), single_insn_field, (bits-> value << (bits->field->last - bits->opcode->last))); } else { lf_printf (file, "%d /* %s == %d */", (atol (entry_name + strlen (single_insn_field) + strlen ("_is_")) == bits->value), single_insn_field, bits->value); } } else { /* put the field in the local variable, possibly also enter it into the cache */ expression = "extraction"; /* handle the cache */ if ((what_to_do & get_values_from_icache) || (what_to_do & put_values_in_icache)) { lf_printf (file, "cache_entry->crack.%s.%s", format_name, entry_name); if (what_to_do & put_values_in_icache) /* also put it in the cache? */ { lf_printf (file, " = "); } } if ((what_to_do & put_values_in_icache) || what_to_do == do_not_use_icache) { if (cur_field != NULL) { if (entry_expression != NULL && strlen (entry_expression) > 0) error (line, "Instruction field entry with nonempty expression\n"); if (cur_field->first == 0 && cur_field->last == options.insn_bit_size - 1) lf_printf (file, "(instruction_%d)", cur_field->word_nr); else if (cur_field->last == options.insn_bit_size - 1) lf_printf (file, "MASKED%d (instruction_%d, %d, %d)", options.insn_bit_size, cur_field->word_nr, i2target (options.hi_bit_nr, cur_field->first), i2target (options.hi_bit_nr, cur_field->last)); else lf_printf (file, "EXTRACTED%d (instruction_%d, %d, %d)", options.insn_bit_size, cur_field->word_nr, i2target (options.hi_bit_nr, cur_field->first), i2target (options.hi_bit_nr, cur_field->last)); } else { lf_printf (file, "%s", entry_expression); } } } switch (what_to_declare) { case define_variables: lf_printf (file, ")"); break; case undef_variables: break; case declare_variables: lf_printf (file, ";"); break; } ASSERT (reason != NULL && expression != NULL); lf_printf (file, " /* %s - %s */\n", reason, expression); }