void print_my_defines(lf *file, insn_bits *expanded_bits, table_entry *file_entry) { /* #define MY_INDEX xxxxx */ lf_indent_suppress(file); lf_printf(file, "#undef MY_INDEX\n"); lf_indent_suppress(file); lf_printf(file, "#define MY_INDEX "); print_function_name(file, file_entry->fields[insn_name], NULL, function_name_prefix_itable); lf_printf(file, "\n"); /* #define MY_PREFIX xxxxxx */ lf_indent_suppress(file); lf_printf(file, "#undef MY_PREFIX\n"); lf_indent_suppress(file); lf_printf(file, "#define MY_PREFIX "); print_function_name(file, file_entry->fields[insn_name], expanded_bits, function_name_prefix_none); lf_printf(file, "\n"); }
static void itable_print_enum (lf *file, filter *set, char *name) { char *elem; lf_printf (file, "typedef enum {\n"); lf_indent (file, +2); for (elem = filter_next (set, ""); elem != NULL; elem = filter_next (set, elem)) { lf_printf (file, "%sitable_%s_%s,\n", options.module.itable.prefix.l, name, elem); if (strlen (options.module.itable.prefix.l) > 0) { lf_indent_suppress (file); lf_printf (file, "#define itable_%s_%s %sitable_%s_%s\n", name, elem, options.module.itable.prefix.l, name, elem); } } lf_printf (file, "nr_%sitable_%ss,\n", options.module.itable.prefix.l, name); lf_indent (file, -2); lf_printf (file, "} %sitable_%ss;\n", options.module.itable.prefix.l, name); if (strlen (options.module.itable.prefix.l) > 0) { lf_indent_suppress (file); lf_printf (file, "#define itable_%ss %sitable_%ss\n", name, options.module.itable.prefix.l, name); lf_indent_suppress (file); lf_printf (file, "#define nr_itable_%ss nr_%sitable_%ss\n", name, options.module.itable.prefix.l, name); } }
static void print_engine_issue_postfix_hook (lf *file) { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n"); lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); lf_printf (file, "\n"); }
static void gen_idecode_h (lf *file, gen_table *gen, insn_table *insns, cache_entry *cache_rules) { lf_printf (file, "typedef unsigned%d %sinstruction_word;\n", options.insn_bit_size, options.module.global.prefix.l); if (options.gen.delayed_branch) { lf_printf (file, "typedef struct _%sinstruction_address {\n", options.module.global.prefix.l); lf_printf (file, " address_word ip; /* instruction pointer */\n"); lf_printf (file, " address_word dp; /* delayed-slot pointer */\n"); lf_printf (file, "} %sinstruction_address;\n", options.module.global.prefix.l); } else { lf_printf (file, "typedef address_word %sinstruction_address;\n", options.module.global.prefix.l); } if (options.gen.nia == nia_is_invalid && strlen (options.module.global.prefix.u) > 0) { lf_indent_suppress (file); lf_printf (file, "#define %sINVALID_INSTRUCTION_ADDRESS ", options.module.global.prefix.u); lf_printf (file, "INVALID_INSTRUCTION_ADDRESS\n"); } lf_printf (file, "\n"); print_icache_struct (file, insns, cache_rules); lf_printf (file, "\n"); if (options.gen.icache) { ERROR ("FIXME - idecode with icache suffering from bit-rot"); } else { gen_list *entry; for (entry = gen->tables; entry != NULL; entry = entry->next) { print_idecode_issue_function_header (file, (options.gen.multi_sim ? entry->model->name : NULL), is_function_declaration, 1/*ALWAYS ONE WORD*/); } if (options.gen.multi_sim) { print_idecode_issue_function_header (file, NULL, is_function_variable, 1/*ALWAYS ONE WORD*/); } } }
static void print_support_function_name (lf *file, function_entry * function, int is_function_definition) { if (function->is_internal) { lf_print__function_type_function (file, print_semantic_function_type, "INLINE_SUPPORT", (is_function_definition ? "\n" : " ")); print_function_name (file, function->name, NULL, NULL, NULL, function_name_prefix_semantics); lf_printf (file, "\n("); lf_indent (file, +1); print_semantic_function_formal (file, 0); lf_indent (file, -1); lf_printf (file, ")"); if (!is_function_definition) lf_printf (file, ";"); lf_printf (file, "\n"); } else { /* map the name onto a globally valid name */ if (!is_function_definition && strcmp (options.module.support.prefix.l, "") != 0) { lf_indent_suppress (file); lf_printf (file, "#define %s %s%s\n", function->name, options.module.support.prefix.l, function->name); } lf_print__function_type (file, function->type, "INLINE_SUPPORT", (is_function_definition ? "\n" : " ")); lf_printf (file, "%s%s\n(", options.module.support.prefix.l, function->name); if (options.gen.smp) lf_printf (file, "sim_cpu *cpu, %sinstruction_address cia, int MY_INDEX", options.module.support.prefix.l); else lf_printf (file, "SIM_DESC sd, %sinstruction_address cia, int MY_INDEX", options.module.support.prefix.l); if (function->param != NULL && strlen (function->param) > 0) lf_printf (file, ", %s", function->param); lf_printf (file, ")%s", (is_function_definition ? "\n" : ";\n")); } }
void print_my_defines (lf *file, const char *basename, const char *format_name, opcode_bits *expanded_bits) { /* #define MY_INDEX xxxxx */ lf_indent_suppress (file); lf_printf (file, "#undef MY_INDEX\n"); lf_indent_suppress (file); lf_printf (file, "#define MY_INDEX "); print_function_name (file, basename, format_name, NULL, NULL, function_name_prefix_itable); lf_printf (file, "\n"); /* #define MY_PREFIX xxxxxx */ lf_indent_suppress (file); lf_printf (file, "#undef "); print_function_name (file, basename, format_name, NULL, expanded_bits, function_name_prefix_none); lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#undef MY_PREFIX\n"); lf_indent_suppress (file); lf_printf (file, "#define MY_PREFIX "); print_function_name (file, basename, format_name, NULL, expanded_bits, function_name_prefix_none); lf_printf (file, "\n"); /* #define MY_NAME xxxxxx */ lf_indent_suppress (file); lf_indent_suppress (file); lf_printf (file, "#undef MY_NAME\n"); lf_indent_suppress (file); lf_printf (file, "#define MY_NAME \""); print_function_name (file, basename, format_name, NULL, expanded_bits, function_name_prefix_none); lf_printf (file, "\"\n"); }
int lf_print__external_ref (lf *file, int line_nr, const char *file_name) { int nr = 0; switch (file->references) { case lf_include_references: lf_indent_suppress (file); nr += lf_putstr (file, "#line "); nr += lf_putint (file, line_nr); nr += lf_putstr (file, " \""); nr += lf_putstr (file, file_name); nr += lf_putstr (file, "\"\n"); break; case lf_omit_references: nr += lf_putstr (file, "/* "); nr += lf_putstr (file, file_name); nr += lf_putstr (file, ":"); nr += lf_putint (file, line_nr); nr += lf_putstr (file, "*/\n"); break; } return nr; }
extern void gen_itable_h (lf *file, insn_table *isa) { itable_info *info = ZALLOC (itable_info); /* output an enumerated type for each instruction */ lf_printf (file, "typedef enum {\n"); insn_table_traverse_insn (file, isa, itable_h_insn, info); lf_printf (file, " nr_%sitable_entries,\n", options.module.itable.prefix.l); lf_printf (file, "} %sitable_index;\n", options.module.itable.prefix.l); lf_printf (file, "\n"); /* output an enumeration type for each flag */ itable_print_enum (file, isa->flags, "flag"); lf_printf (file, "extern const char *%sitable_flag_names[];\n", options.module.itable.prefix.l); lf_printf (file, "\n"); /* output an enumeration of all the possible options */ itable_print_enum (file, isa->options, "option"); lf_printf (file, "extern const char *%sitable_option_names[];\n", options.module.itable.prefix.l); lf_printf (file, "\n"); /* output an enumeration of all the processor models */ itable_print_enum (file, isa->model->processors, "processor"); lf_printf (file, "extern const char *%sitable_processor_names[];\n", options.module.itable.prefix.l); lf_printf (file, "\n"); /* output the table that contains the actual instruction info */ lf_printf (file, "typedef struct _%sitable_instruction_info {\n", options.module.itable.prefix.l); lf_printf (file, " %sitable_index nr;\n", options.module.itable.prefix.l); lf_printf (file, " char *format;\n"); lf_printf (file, " char *form;\n"); lf_printf (file, " char *flags;\n"); /* nr_itable_* may be zero, so we add 1 to avoid an illegal zero-sized array. */ lf_printf (file, " char flag[nr_%sitable_flags + 1];\n", options.module.itable.prefix.l); lf_printf (file, " char *options;\n"); lf_printf (file, " char option[nr_%sitable_options + 1];\n", options.module.itable.prefix.l); lf_printf (file, " char *processors;\n"); lf_printf (file, " char processor[nr_%sitable_processors + 1];\n", options.module.itable.prefix.l); lf_printf (file, " char *name;\n"); lf_printf (file, " char *file;\n"); lf_printf (file, " int line_nr;\n"); lf_printf (file, "} %sitable_info;\n", options.module.itable.prefix.l); lf_printf (file, "\n"); lf_printf (file, "extern %sitable_info %sitable[nr_%sitable_entries];\n", options.module.itable.prefix.l, options.module.itable.prefix.l, options.module.itable.prefix.l); if (strlen (options.module.itable.prefix.l) > 0) { lf_indent_suppress (file); lf_printf (file, "#define itable %sitable\n", options.module.itable.prefix.l); } lf_printf (file, "\n"); /* output an enum defining the max size of various itable members */ lf_printf (file, "enum {\n"); lf_printf (file, " sizeof_%sitable_form = %d,\n", options.module.itable.prefix.l, info->sizeof_form); lf_printf (file, " sizeof_%sitable_name = %d,\n", options.module.itable.prefix.l, info->sizeof_name); lf_printf (file, " sizeof_%sitable_file = %d,\n", options.module.itable.prefix.l, info->sizeof_file); lf_printf (file, "};\n"); }
extern void gen_support_h (lf *file, insn_table *table) { /* output the definition of `SD_' */ if (options.gen.smp) { lf_printf (file, "#define SD CPU_STATE (cpu)\n"); lf_printf (file, "#define CPU cpu\n"); lf_printf (file, "#define CPU_ cpu\n"); } else { lf_printf (file, "#define SD sd\n"); lf_printf (file, "#define CPU (STATE_CPU (sd, 0))\n"); lf_printf (file, "#define CPU_ sd\n"); } lf_printf (file, "#define CIA_ cia\n"); if (options.gen.delayed_branch) { lf_printf (file, "#define CIA cia.ip\n"); lf_printf (file, "/* #define NIA nia.dp -- do not define, ambigious */\n"); } else { lf_printf (file, "#define CIA cia\n"); lf_printf (file, "#define NIA nia\n"); } lf_printf (file, "\n"); lf_printf (file, "#define SD_ CPU_, CIA_, MY_INDEX\n"); lf_printf (file, "#define _SD SD_ /* deprecated */\n"); lf_printf (file, "\n"); /* Map <PREFIX>_xxxx onto the shorter xxxx for the following names: instruction_word idecode_issue semantic_illegal Map defined here as name space problems are created when the name is defined in idecode.h */ if (strcmp (options.module.idecode.prefix.l, "") != 0) { lf_indent_suppress (file); lf_printf (file, "#define %s %s%s\n", "instruction_word", options.module.idecode.prefix.l, "instruction_word"); lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#define %s %s%s\n", "idecode_issue", options.module.idecode.prefix.l, "idecode_issue"); lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#define %s %s%s\n", "semantic_illegal", options.module.idecode.prefix.l, "semantic_illegal"); lf_printf (file, "\n"); } /* output a declaration for all functions */ function_entry_traverse (file, table->functions, support_h_function, NULL); lf_printf (file, "\n"); lf_printf (file, "#if defined(SUPPORT_INLINE)\n"); lf_printf (file, "# if ((SUPPORT_INLINE & INCLUDE_MODULE)\\\n"); lf_printf (file, " && (SUPPORT_INLINE & INCLUDED_BY_MODULE))\n"); lf_printf (file, "# include \"%ssupport.c\"\n", options.module.support.prefix.l); lf_printf (file, "# endif\n"); lf_printf (file, "#endif\n"); }
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"); }
void print_semantic_body (lf *file, insn_entry * instruction, opcode_bits *expanded_bits, insn_opcodes *opcodes) { /* validate the instruction, if a cache this has already been done */ if (!options.gen.icache) { print_idecode_validate (file, instruction, opcodes); } print_itrace (file, instruction, 0 /*put_value_in_cache */ ); /* generate the instruction profile call - this is delayed until after the instruction has been verified. The count macro generated is prefixed by ITABLE_PREFIX */ { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n", options.module.itable.prefix.u); lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n", options.module.itable.prefix.u); lf_indent_suppress (file); lf_printf (file, "#endif\n"); } /* generate the model call - this is delayed until after the instruction has been verified */ { lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (WITH_MON)\n"); lf_printf (file, "/* monitoring: */\n"); lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n"); lf_printf (file, " mon_issue ("); print_function_name (file, instruction->name, instruction->format_name, NULL, NULL, function_name_prefix_itable); lf_printf (file, ", cpu, cia);\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); lf_printf (file, "\n"); } /* determine the new instruction address */ { lf_printf (file, "/* keep the next instruction address handy */\n"); if (options.gen.nia == nia_is_invalid) { lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n", options.module.global.prefix.u); } else { int nr_immeds = instruction->nr_words - 1; if (options.gen.delayed_branch) { if (nr_immeds > 0) { lf_printf (file, "cia.dp += %d * %d; %s\n", options.insn_bit_size / 8, nr_immeds, "/* skip dp immeds */"); } lf_printf (file, "nia.ip = cia.dp; %s\n", "/* instruction pointer */"); lf_printf (file, "nia.dp = cia.dp + %d; %s\n", options.insn_bit_size / 8, "/* delayed-slot pointer */"); } else { if (nr_immeds > 0) { lf_printf (file, "nia = cia + %d * (%d + 1); %s\n", options.insn_bit_size / 8, nr_immeds, "/* skip immeds as well */"); } else { lf_printf (file, "nia = cia + %d;\n", options.insn_bit_size / 8); } } } } /* if conditional, generate code to verify that the instruction should be issued */ if (filter_is_member (instruction->options, "c") || options.gen.conditional_issue) { lf_printf (file, "\n"); lf_printf (file, "/* execute only if conditional passes */\n"); lf_printf (file, "if (IS_CONDITION_OK)\n"); lf_printf (file, " {\n"); lf_indent (file, +4); /* FIXME - need to log a conditional failure */ } /* Architecture expects a REG to be zero. Instead of having to check every read to see if it is refering to that REG just zap it at the start of every instruction */ if (options.gen.zero_reg) { lf_printf (file, "\n"); lf_printf (file, "/* Architecture expects REG to be zero */\n"); lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr); } /* generate the code (or at least something */ lf_printf (file, "\n"); lf_printf (file, "/* semantics: */\n"); if (instruction->code != NULL) { /* true code */ lf_printf (file, "{\n"); lf_indent (file, +2); lf_print__line_ref (file, instruction->code->line); table_print_code (file, instruction->code); lf_indent (file, -2); lf_printf (file, "}\n"); lf_print__internal_ref (file); } else if (filter_is_member (instruction->options, "nop")) { lf_print__internal_ref (file); } else { const char *prefix = "sim_engine_abort ("; int indent = strlen (prefix); /* abort so it is implemented now */ lf_print__line_ref (file, instruction->line); lf_printf (file, "%sSD, CPU, cia, \\\n", prefix); lf_indent (file, +indent); lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n", filter_filename (instruction->line->file_name), instruction->line->line_nr); lf_printf (file, "(long) CIA, \\\n"); lf_printf (file, "%sitable[MY_INDEX].name);\n", options.module.itable.prefix.l); lf_indent (file, -indent); lf_print__internal_ref (file); } /* Close off the conditional execution */ if (filter_is_member (instruction->options, "c") || options.gen.conditional_issue) { lf_indent (file, -4); 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); }
void print_itrace (lf *file, insn_entry *insn, int idecode) { /* NB: Here we escape each EOLN. This is so that the the compiler treats a trace function call as a single line. Consequently any errors in the line are refered back to the same igen assembler source line */ const char *phase = (idecode) ? "DECODE" : "INSN"; lf_printf (file, "\n"); lf_indent_suppress (file); lf_printf (file, "#if defined (WITH_TRACE)\n"); lf_printf (file, "/* generate a trace prefix if any tracing enabled */\n"); lf_printf (file, "if (TRACE_ANY_P (CPU))\n"); lf_printf (file, " {\n"); lf_indent (file, +4); { if (insn->mnemonics != NULL) { insn_mnemonic_entry *assembler = insn->mnemonics; int is_first = 1; do { if (assembler->condition != NULL) { int indent; lf_printf (file, "%sif (%s)\n", is_first ? "" : "else ", assembler->condition); lf_indent (file, +2); lf_print__line_ref (file, assembler->line); indent = print_itrace_prefix (file); print_itrace_format (file, assembler); lf_print__internal_ref (file); lf_indent (file, -indent); lf_indent (file, -2); if (assembler->next == NULL) error (assembler->line, "Missing final unconditional assembler\n"); } else { int indent; if (!is_first) { lf_printf (file, "else\n"); lf_indent (file, +2); } lf_print__line_ref (file, assembler->line); indent = print_itrace_prefix (file); print_itrace_format (file, assembler); lf_print__internal_ref (file); lf_indent (file, -indent); if (!is_first) lf_indent (file, -2); if (assembler->next != NULL) error (assembler->line, "Unconditional assembler is not last\n"); } is_first = 0; assembler = assembler->next; } while (assembler != NULL); } else { int indent; lf_indent (file, +2); lf_print__line_ref (file, insn->line); indent = print_itrace_prefix (file); lf_printf (file, "%%s\", \\\n"); lf_printf (file, "itable[MY_INDEX].name);\n"); lf_print__internal_ref (file); lf_indent (file, -indent); lf_indent (file, -2); } lf_printf (file, "/* trace the instruction execution if enabled */\n"); lf_printf (file, "if (TRACE_%s_P (CPU))\n", phase); lf_printf (file, " trace_generic (SD, CPU, TRACE_%s_IDX, \" %%s\", itable[MY_INDEX].name);\n", phase); } lf_indent (file, -4); lf_printf (file, " }\n"); lf_indent_suppress (file); lf_printf (file, "#endif\n"); }