diff --git a/src/compiler/isaspec/isa.py b/src/compiler/isaspec/isa.py index 501cb6d0be8..23e392bc619 100644 --- a/src/compiler/isaspec/isa.py +++ b/src/compiler/isaspec/isa.py @@ -494,7 +494,7 @@ class ISA(object): # Validate that all bitset fields have valid types, and in # the case of bitset type, the sizes match: - builtin_types = ['branch', 'absbranch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum'] + builtin_types = ['branch', 'absbranch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum', 'custom'] for bitset_name, bitset in self.bitsets.items(): if bitset.extends is not None: assert bitset.extends in self.bitsets, "{} extends invalid type: {}".format( diff --git a/src/compiler/isaspec/isaspec.h b/src/compiler/isaspec/isaspec.h index fdfc28117d3..da4ed3fb162 100644 --- a/src/compiler/isaspec/isaspec.h +++ b/src/compiler/isaspec/isaspec.h @@ -51,6 +51,17 @@ struct isa_entrypoint { uint32_t offset; }; +struct isa_print_state { + FILE *out; + + /** + * Column number of current line + */ + unsigned line_column; +}; + +void isa_print(struct isa_print_state *state, const char *fmt, ...) PRINTFLIKE(2, 3); + struct isa_decode_options { uint32_t gpu_id; @@ -83,6 +94,11 @@ struct isa_decode_options { */ void (*field_cb)(void *data, const char *field_name, struct isa_decode_value *val); + /** + * Callback for fields that need custom code to print their value. + */ + void (*field_print_cb)(struct isa_print_state *print, const char *field_name, uint64_t val); + /** * Callback prior to instruction decode */ diff --git a/src/compiler/isaspec/isaspec_decode_decl.h b/src/compiler/isaspec/isaspec_decode_decl.h index 93367f17edf..97f16fcd6ff 100644 --- a/src/compiler/isaspec/isaspec_decode_decl.h +++ b/src/compiler/isaspec/isaspec_decode_decl.h @@ -90,6 +90,9 @@ struct isa_field { TYPE_BOOL, TYPE_ENUM, + /* For fields that must be printed via a user-provided callback */ + TYPE_CUSTOM, + /* To assert a certain value in a given range of bits.. not * used for pattern matching, but allows an override to specify * that a certain bitpattern in some "unused" bits is expected diff --git a/src/compiler/isaspec/isaspec_decode_impl.c b/src/compiler/isaspec/isaspec_decode_impl.c index 3b2c59a4111..3b97931f77b 100644 --- a/src/compiler/isaspec/isaspec_decode_impl.c +++ b/src/compiler/isaspec/isaspec_decode_impl.c @@ -118,7 +118,8 @@ struct decode_scope { */ struct decode_state { const struct isa_decode_options *options; - FILE *out; + + struct isa_print_state print; /** * Current instruction being decoded: @@ -130,11 +131,6 @@ struct decode_state { */ unsigned num_instr; - /** - * Column number of current line - */ - unsigned line_column; - /** * Bitset of instructions that are branch targets (if options->branch_labels * is enabled) @@ -180,8 +176,8 @@ struct decode_state { char *errors[4]; }; -static void -print(struct decode_state *state, const char *fmt, ...) +void +isa_print(struct isa_print_state *state, const char *fmt, ...) { char *buffer; va_list args; @@ -203,7 +199,7 @@ print(struct decode_state *state, const char *fmt, ...) if (c == '\n') { state->line_column = 0; } - } + } free(buffer); @@ -237,9 +233,9 @@ flush_errors(struct decode_state *state) { unsigned num_errors = state->num_errors; if (num_errors > 0) - print(state, "\t; "); + isa_print(&state->print, "\t; "); for (unsigned i = 0; i < num_errors; i++) { - print(state, "%s%s", (i > 0) ? ", " : "", state->errors[i]); + isa_print(&state->print, "%s%s", (i > 0) ? ", " : "", state->errors[i]); free(state->errors[i]); } state->num_errors = 0; @@ -502,12 +498,12 @@ display_enum_field(struct decode_scope *scope, const struct isa_field *field, bi for (unsigned i = 0; i < e->num_values; i++) { if (e->values[i].val == ui) { - print(scope->state, "%s", e->values[i].display); + isa_print(&scope->state->print, "%s", e->values[i].display); return; } } - print(scope->state, "%u", (unsigned)ui); + isa_print(&scope->state->print, "%u", (unsigned)ui); } static const struct isa_field * @@ -566,6 +562,7 @@ display_field(struct decode_scope *scope, const char *field_name) { const struct isa_decode_options *options = scope->state->options; struct decode_state *state = scope->state; + struct isa_print_state *print = &state->print; size_t field_name_len = strlen(field_name); int num_align = 0; @@ -581,8 +578,8 @@ display_field(struct decode_scope *scope, const char *field_name) /* Special case ':algin=' should only do alignment */ if (field_name == align) { - while (scope->state->line_column < num_align) - print(state, " "); + while (scope->state->print.line_column < num_align) + isa_print(print, " "); return; } @@ -595,10 +592,10 @@ display_field(struct decode_scope *scope, const char *field_name) }); } - while (scope->state->line_column < num_align) - print(state, " "); + while (scope->state->print.line_column < num_align) + isa_print(print, " "); - print(scope->state, "%s", scope->bitset->name); + isa_print(print, "%s", scope->bitset->name); return; } @@ -620,8 +617,8 @@ display_field(struct decode_scope *scope, const char *field_name) unsigned width = 1 + field->high - field->low; - while (scope->state->line_column < num_align) - print(state, " "); + while (scope->state->print.line_column < num_align) + isa_print(print, " "); switch (field->type) { /* Basic types: */ @@ -636,10 +633,10 @@ display_field(struct decode_scope *scope, const char *field_name) } if (offset < scope->state->num_instr) { if (field->call) { - print(scope->state, "fxn%d", offset); + isa_print(print, "fxn%d", offset); BITSET_SET(scope->state->call_targets, offset); } else { - print(scope->state, "l%d", offset); + isa_print(print, "l%d", offset); BITSET_SET(scope->state->branch_targets, offset); } break; @@ -647,45 +644,53 @@ display_field(struct decode_scope *scope, const char *field_name) } FALLTHROUGH; case TYPE_INT: - print(scope->state, "%"PRId64, util_sign_extend(val, width)); + isa_print(print, "%"PRId64, util_sign_extend(val, width)); break; case TYPE_UINT: - print(scope->state, "%"PRIu64, val); + isa_print(print, "%"PRIu64, val); break; case TYPE_HEX: // TODO format # of digits based on field width? - print(scope->state, "%"PRIx64, val); + isa_print(print, "%"PRIx64, val); break; case TYPE_OFFSET: if (val != 0) { - print(scope->state, "%+"PRId64, util_sign_extend(val, width)); + isa_print(print, "%+"PRId64, util_sign_extend(val, width)); } break; case TYPE_UOFFSET: if (val != 0) { - print(scope->state, "+%"PRIu64, val); + isa_print(print, "+%"PRIu64, val); } break; case TYPE_FLOAT: if (width == 16) { - print(scope->state, "%f", _mesa_half_to_float(val)); + isa_print(print, "%f", _mesa_half_to_float(val)); } else { assert(width == 32); - print(scope->state, "%f", uif(val)); + isa_print(print, "%f", uif(val)); } break; case TYPE_BOOL: if (field->display) { if (val) { - print(scope->state, "%s", field->display); + isa_print(print, "%s", field->display); } } else { - print(scope->state, "%u", (unsigned)val); + isa_print(print, "%u", (unsigned)val); } break; case TYPE_ENUM: display_enum_field(scope, field, v); break; + case TYPE_CUSTOM: + /* The user has to provide a field_print_cb, but this can + * still be NULL during the branch offset pre-pass. + */ + if (state->options->field_print_cb) { + state->options->field_print_cb(print, field_name, val); + } + break; case TYPE_ASSERT: /* assert fields are not for display */ @@ -728,8 +733,8 @@ display(struct decode_scope *scope) p = e; } else { - fputc(*p, scope->state->out); - scope->state->line_column++; + fputc(*p, scope->state->print.out); + scope->state->print.line_column++; } p++; } @@ -747,7 +752,7 @@ decode(struct decode_state *state, void *bin, int sz) bitmask_t instr = { 0 }; next_instruction(&instr, &instrs[state->n * BITMASK_WORDS]); - state->line_column = 0; + state->print.line_column = 0; if (state->options->max_errors && (errors > state->options->max_errors)) { break; @@ -767,7 +772,7 @@ decode(struct decode_state *state, void *bin, int sz) state->options->instr_cb(state->options->cbdata, state->n, instr.bitset); } - print(state, "\n"); + isa_print(&state->print, "\n"); } while (state->next_entrypoint != state->end_entrypoint && @@ -776,7 +781,7 @@ decode(struct decode_state *state, void *bin, int sz) state->options->instr_cb(state->options->cbdata, state->n, instr.bitset); } - print(state, "%s:\n", state->next_entrypoint->name); + isa_print(&state->print, "%s:\n", state->next_entrypoint->name); state->next_entrypoint++; } @@ -785,7 +790,7 @@ decode(struct decode_state *state, void *bin, int sz) state->options->instr_cb(state->options->cbdata, state->n, instr.bitset); } - print(state, "fxn%d:\n", state->n); + isa_print(&state->print, "fxn%d:\n", state->n); } if (BITSET_TEST(state->branch_targets, state->n)) { @@ -793,7 +798,7 @@ decode(struct decode_state *state, void *bin, int sz) state->options->instr_cb(state->options->cbdata, state->n, instr.bitset); } - print(state, "l%d:\n", state->n); + isa_print(&state->print, "l%d:\n", state->n); } } @@ -804,9 +809,9 @@ decode(struct decode_state *state, void *bin, int sz) const struct isa_bitset *b = find_bitset(state, __instruction, instr); if (!b) { if (state->options->no_match_cb) { - state->options->no_match_cb(state->out, instr.bitset, BITMASK_WORDS); + state->options->no_match_cb(state->print.out, instr.bitset, BITMASK_WORDS); } else { - print(state, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset)); + isa_print(&state->print, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset)); } errors++; continue; @@ -820,7 +825,7 @@ decode(struct decode_state *state, void *bin, int sz) } else { errors = 0; } - print(state, "\n"); + isa_print(&state->print, "\n"); pop_scope(scope); @@ -860,10 +865,10 @@ isa_decode(void *bin, int sz, FILE *out, const struct isa_decode_options *option sizeof(BITSET_WORD) * BITSET_WORDS(state->num_instr)); /* Do a pre-pass to find all the branch targets: */ - state->out = fopen("/dev/null", "w"); + state->print.out = fopen("/dev/null", "w"); state->options = &default_options; /* skip hooks for prepass */ decode(state, bin, sz); - fclose(state->out); + fclose(state->print.out); if (options) { state->options = options; } @@ -884,7 +889,7 @@ isa_decode(void *bin, int sz, FILE *out, const struct isa_decode_options *option } } - state->out = out; + state->print.out = out; decode(state, bin, sz);