decode.c revision 7ec681f3
17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2020 Google, Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <assert.h> 257ec681f3Smrg#include <inttypes.h> 267ec681f3Smrg#include <stdbool.h> 277ec681f3Smrg#include <stdint.h> 287ec681f3Smrg#include <stdio.h> 297ec681f3Smrg#include <stdlib.h> 307ec681f3Smrg#include <string.h> 317ec681f3Smrg 327ec681f3Smrg#include "util/bitset.h" 337ec681f3Smrg#include "util/compiler.h" 347ec681f3Smrg#include "util/half_float.h" 357ec681f3Smrg#include "util/hash_table.h" 367ec681f3Smrg#include "util/ralloc.h" 377ec681f3Smrg#include "util/u_debug.h" 387ec681f3Smrg#include "util/u_math.h" 397ec681f3Smrg 407ec681f3Smrg#include "decode.h" 417ec681f3Smrg#include "isa.h" 427ec681f3Smrg 437ec681f3Smrg/** 447ec681f3Smrg * The set of leaf node bitsets in the bitset hiearchy which defines all 457ec681f3Smrg * the possible instructions. 467ec681f3Smrg * 477ec681f3Smrg * TODO maybe we want to pass this in as parameter so this same decoder 487ec681f3Smrg * can work with multiple different instruction sets. 497ec681f3Smrg */ 507ec681f3Smrgextern const struct isa_bitset *__instruction[]; 517ec681f3Smrg 527ec681f3Smrgstruct decode_state; 537ec681f3Smrg 547ec681f3Smrg/** 557ec681f3Smrg * Decode scope. When parsing a field that is itself a bitset, we push a 567ec681f3Smrg * new scope to the stack. A nested bitset is allowed to resolve fields 577ec681f3Smrg * from an enclosing scope (needed, for example, to decode src register 587ec681f3Smrg * bitsets, where half/fullness is determined by fields outset if bitset 597ec681f3Smrg * in the instruction containing the bitset. 607ec681f3Smrg * 617ec681f3Smrg * But the field being resolved could be a derived field, or different 627ec681f3Smrg * depending on an override at a higher level of the stack, requiring 637ec681f3Smrg * expression evaluation which could in turn reference variables which 647ec681f3Smrg * triggers a recursive field lookup. But those lookups should not start 657ec681f3Smrg * from the top of the stack, but instead the current stack level. This 667ec681f3Smrg * prevents a field from accidentally resolving to different values 677ec681f3Smrg * depending on the starting point of the lookup. (Not only causing 687ec681f3Smrg * confusion, but this is behavior we don't want to depend on if we 697ec681f3Smrg * wanted to optimize things by caching field lookup results.) 707ec681f3Smrg */ 717ec681f3Smrgstruct decode_scope { 727ec681f3Smrg /** 737ec681f3Smrg * Enclosing scope 747ec681f3Smrg */ 757ec681f3Smrg struct decode_scope *parent; 767ec681f3Smrg 777ec681f3Smrg /** 787ec681f3Smrg * Current bitset value being decoded 797ec681f3Smrg */ 807ec681f3Smrg bitmask_t val; 817ec681f3Smrg 827ec681f3Smrg /** 837ec681f3Smrg * Current bitset. 847ec681f3Smrg */ 857ec681f3Smrg const struct isa_bitset *bitset; 867ec681f3Smrg 877ec681f3Smrg /** 887ec681f3Smrg * Field name remapping. 897ec681f3Smrg */ 907ec681f3Smrg const struct isa_field_params *params; 917ec681f3Smrg 927ec681f3Smrg /** 937ec681f3Smrg * Pointer back to decode state, for convenience. 947ec681f3Smrg */ 957ec681f3Smrg struct decode_state *state; 967ec681f3Smrg 977ec681f3Smrg /** 987ec681f3Smrg * Cache expression evaluation results. Expressions for overrides can 997ec681f3Smrg * be repeatedly evaluated for each field being resolved. And each 1007ec681f3Smrg * field reference to a derived field (potentially from another expr) 1017ec681f3Smrg * would require re-evaluation. But for a given scope, each evaluation 1027ec681f3Smrg * of an expression gives the same result. So we can cache to speed 1037ec681f3Smrg * things up. 1047ec681f3Smrg * 1057ec681f3Smrg * TODO we could maybe be clever and assign a unique idx to each expr 1067ec681f3Smrg * and use a direct lookup table? Would be a bit more clever if it was 1077ec681f3Smrg * smart enough to allow unrelated expressions that are never involved 1087ec681f3Smrg * in a given scope to have overlapping cache lookup idx's. 1097ec681f3Smrg */ 1107ec681f3Smrg struct hash_table *cache; 1117ec681f3Smrg}; 1127ec681f3Smrg 1137ec681f3Smrg/** 1147ec681f3Smrg * Current decode state 1157ec681f3Smrg */ 1167ec681f3Smrgstruct decode_state { 1177ec681f3Smrg const struct isa_decode_options *options; 1187ec681f3Smrg FILE *out; 1197ec681f3Smrg 1207ec681f3Smrg /** 1217ec681f3Smrg * Current instruction being decoded: 1227ec681f3Smrg */ 1237ec681f3Smrg unsigned n; 1247ec681f3Smrg 1257ec681f3Smrg /** 1267ec681f3Smrg * Number of instructions being decoded 1277ec681f3Smrg */ 1287ec681f3Smrg unsigned num_instr; 1297ec681f3Smrg 1307ec681f3Smrg /** 1317ec681f3Smrg * Column number of current line 1327ec681f3Smrg */ 1337ec681f3Smrg unsigned line_column; 1347ec681f3Smrg 1357ec681f3Smrg /** 1367ec681f3Smrg * Bitset of instructions that are branch targets (if options->branch_labels 1377ec681f3Smrg * is enabled) 1387ec681f3Smrg */ 1397ec681f3Smrg BITSET_WORD *branch_targets; 1407ec681f3Smrg 1417ec681f3Smrg /** 1427ec681f3Smrg * We allow a limited amount of expression evaluation recursion, but 1437ec681f3Smrg * not recursive evaluation of any given expression, to prevent infinite 1447ec681f3Smrg * recursion. 1457ec681f3Smrg */ 1467ec681f3Smrg int expr_sp; 1477ec681f3Smrg isa_expr_t expr_stack[8]; 1487ec681f3Smrg 1497ec681f3Smrg /** 1507ec681f3Smrg * Current topmost/innermost level of scope used for decoding fields, 1517ec681f3Smrg * including derived fields which may in turn rely on decoding other 1527ec681f3Smrg * fields, potentially from a lower/out level in the stack. 1537ec681f3Smrg */ 1547ec681f3Smrg struct decode_scope *scope; 1557ec681f3Smrg 1567ec681f3Smrg /** 1577ec681f3Smrg * A small fixed upper limit on # of decode errors to capture per- 1587ec681f3Smrg * instruction seems reasonable. 1597ec681f3Smrg */ 1607ec681f3Smrg unsigned num_errors; 1617ec681f3Smrg char *errors[4]; 1627ec681f3Smrg}; 1637ec681f3Smrg 1647ec681f3Smrgstatic void 1657ec681f3Smrgprint(struct decode_state *state, const char *fmt, ...) 1667ec681f3Smrg{ 1677ec681f3Smrg char *buffer; 1687ec681f3Smrg va_list args; 1697ec681f3Smrg int ret; 1707ec681f3Smrg 1717ec681f3Smrg va_start(args, fmt); 1727ec681f3Smrg ret = vasprintf(&buffer, fmt, args); 1737ec681f3Smrg va_end(args); 1747ec681f3Smrg 1757ec681f3Smrg if (ret != -1) { 1767ec681f3Smrg const size_t len = strlen(buffer); 1777ec681f3Smrg 1787ec681f3Smrg for (size_t i = 0; i < len; i++) { 1797ec681f3Smrg const char c = buffer[i]; 1807ec681f3Smrg 1817ec681f3Smrg fputc(c, state->out); 1827ec681f3Smrg state->line_column++; 1837ec681f3Smrg 1847ec681f3Smrg if (c == '\n') { 1857ec681f3Smrg state->line_column = 0; 1867ec681f3Smrg } 1877ec681f3Smrg } 1887ec681f3Smrg 1897ec681f3Smrg free(buffer); 1907ec681f3Smrg 1917ec681f3Smrg return; 1927ec681f3Smrg } 1937ec681f3Smrg} 1947ec681f3Smrg 1957ec681f3Smrgstatic void display(struct decode_scope *scope); 1967ec681f3Smrgstatic void decode_error(struct decode_state *state, const char *fmt, ...) _util_printf_format(2,3); 1977ec681f3Smrg 1987ec681f3Smrgstatic void 1997ec681f3Smrgdecode_error(struct decode_state *state, const char *fmt, ...) 2007ec681f3Smrg{ 2017ec681f3Smrg if (!state->options->show_errors) { 2027ec681f3Smrg return; 2037ec681f3Smrg } 2047ec681f3Smrg 2057ec681f3Smrg if (state->num_errors == ARRAY_SIZE(state->errors)) { 2067ec681f3Smrg /* too many errors, bail */ 2077ec681f3Smrg return; 2087ec681f3Smrg } 2097ec681f3Smrg 2107ec681f3Smrg va_list ap; 2117ec681f3Smrg va_start(ap, fmt); 2127ec681f3Smrg vasprintf(&state->errors[state->num_errors++], fmt, ap); 2137ec681f3Smrg va_end(ap); 2147ec681f3Smrg} 2157ec681f3Smrg 2167ec681f3Smrgstatic unsigned 2177ec681f3Smrgflush_errors(struct decode_state *state) 2187ec681f3Smrg{ 2197ec681f3Smrg unsigned num_errors = state->num_errors; 2207ec681f3Smrg if (num_errors > 0) 2217ec681f3Smrg print(state, "\t; "); 2227ec681f3Smrg for (unsigned i = 0; i < num_errors; i++) { 2237ec681f3Smrg print(state, "%s%s", (i > 0) ? ", " : "", state->errors[i]); 2247ec681f3Smrg free(state->errors[i]); 2257ec681f3Smrg } 2267ec681f3Smrg state->num_errors = 0; 2277ec681f3Smrg return num_errors; 2287ec681f3Smrg} 2297ec681f3Smrg 2307ec681f3Smrg 2317ec681f3Smrgstatic bool 2327ec681f3Smrgpush_expr(struct decode_state *state, isa_expr_t expr) 2337ec681f3Smrg{ 2347ec681f3Smrg for (int i = state->expr_sp - 1; i > 0; i--) { 2357ec681f3Smrg if (state->expr_stack[i] == expr) { 2367ec681f3Smrg return false; 2377ec681f3Smrg } 2387ec681f3Smrg } 2397ec681f3Smrg state->expr_stack[state->expr_sp++] = expr; 2407ec681f3Smrg return true; 2417ec681f3Smrg} 2427ec681f3Smrg 2437ec681f3Smrgstatic void 2447ec681f3Smrgpop_expr(struct decode_state *state) 2457ec681f3Smrg{ 2467ec681f3Smrg assert(state->expr_sp > 0); 2477ec681f3Smrg state->expr_sp--; 2487ec681f3Smrg} 2497ec681f3Smrg 2507ec681f3Smrgstatic struct decode_scope * 2517ec681f3Smrgpush_scope(struct decode_state *state, const struct isa_bitset *bitset, bitmask_t val) 2527ec681f3Smrg{ 2537ec681f3Smrg struct decode_scope *scope = rzalloc_size(state, sizeof(*scope)); 2547ec681f3Smrg 2557ec681f3Smrg BITSET_COPY(scope->val.bitset, val.bitset); 2567ec681f3Smrg scope->bitset = bitset; 2577ec681f3Smrg scope->parent = state->scope; 2587ec681f3Smrg scope->state = state; 2597ec681f3Smrg 2607ec681f3Smrg state->scope = scope; 2617ec681f3Smrg 2627ec681f3Smrg return scope; 2637ec681f3Smrg} 2647ec681f3Smrg 2657ec681f3Smrgstatic void 2667ec681f3Smrgpop_scope(struct decode_scope *scope) 2677ec681f3Smrg{ 2687ec681f3Smrg assert(scope->state->scope == scope); /* must be top of stack */ 2697ec681f3Smrg 2707ec681f3Smrg scope->state->scope = scope->parent; 2717ec681f3Smrg ralloc_free(scope); 2727ec681f3Smrg} 2737ec681f3Smrg 2747ec681f3Smrg/** 2757ec681f3Smrg * Evaluate an expression, returning it's resulting value 2767ec681f3Smrg */ 2777ec681f3Smrgstatic uint64_t 2787ec681f3Smrgevaluate_expr(struct decode_scope *scope, isa_expr_t expr) 2797ec681f3Smrg{ 2807ec681f3Smrg if (scope->cache) { 2817ec681f3Smrg struct hash_entry *entry = _mesa_hash_table_search(scope->cache, expr); 2827ec681f3Smrg if (entry) { 2837ec681f3Smrg return *(uint64_t *)entry->data; 2847ec681f3Smrg } 2857ec681f3Smrg } else { 2867ec681f3Smrg scope->cache = _mesa_pointer_hash_table_create(scope); 2877ec681f3Smrg } 2887ec681f3Smrg 2897ec681f3Smrg if (!push_expr(scope->state, expr)) 2907ec681f3Smrg return 0; 2917ec681f3Smrg 2927ec681f3Smrg uint64_t ret = expr(scope); 2937ec681f3Smrg 2947ec681f3Smrg pop_expr(scope->state); 2957ec681f3Smrg 2967ec681f3Smrg uint64_t *retp = ralloc_size(scope->cache, sizeof(*retp)); 2977ec681f3Smrg *retp = ret; 2987ec681f3Smrg _mesa_hash_table_insert(scope->cache, expr, retp); 2997ec681f3Smrg 3007ec681f3Smrg return ret; 3017ec681f3Smrg} 3027ec681f3Smrg 3037ec681f3Smrg/** 3047ec681f3Smrg * Find the bitset in NULL terminated bitset hiearchy root table which 3057ec681f3Smrg * matches against 'val' 3067ec681f3Smrg */ 3077ec681f3Smrgstatic const struct isa_bitset * 3087ec681f3Smrgfind_bitset(struct decode_state *state, const struct isa_bitset **bitsets, 3097ec681f3Smrg bitmask_t val) 3107ec681f3Smrg{ 3117ec681f3Smrg const struct isa_bitset *match = NULL; 3127ec681f3Smrg for (int n = 0; bitsets[n]; n++) { 3137ec681f3Smrg if (state->options->gpu_id > bitsets[n]->gen.max) 3147ec681f3Smrg continue; 3157ec681f3Smrg if (state->options->gpu_id < bitsets[n]->gen.min) 3167ec681f3Smrg continue; 3177ec681f3Smrg 3187ec681f3Smrg // m = (val & bitsets[n]->mask) & ~bitsets[n]->dontcare; 3197ec681f3Smrg bitmask_t m = { 0 }; 3207ec681f3Smrg bitmask_t not_dontcare; 3217ec681f3Smrg 3227ec681f3Smrg BITSET_AND(m.bitset, val.bitset, bitsets[n]->mask.bitset); 3237ec681f3Smrg 3247ec681f3Smrg BITSET_COPY(not_dontcare.bitset, bitsets[n]->dontcare.bitset); 3257ec681f3Smrg BITSET_NOT(not_dontcare.bitset); 3267ec681f3Smrg 3277ec681f3Smrg BITSET_AND(m.bitset, m.bitset, not_dontcare.bitset); 3287ec681f3Smrg 3297ec681f3Smrg if (!BITSET_EQUAL(m.bitset, bitsets[n]->match.bitset)) { 3307ec681f3Smrg continue; 3317ec681f3Smrg } 3327ec681f3Smrg 3337ec681f3Smrg /* We should only have exactly one match 3347ec681f3Smrg * 3357ec681f3Smrg * TODO more complete/formal way to validate that any given 3367ec681f3Smrg * bit pattern will only have a single match? 3377ec681f3Smrg */ 3387ec681f3Smrg if (match) { 3397ec681f3Smrg decode_error(state, "bitset conflict: %s vs %s", match->name, 3407ec681f3Smrg bitsets[n]->name); 3417ec681f3Smrg return NULL; 3427ec681f3Smrg } 3437ec681f3Smrg 3447ec681f3Smrg match = bitsets[n]; 3457ec681f3Smrg } 3467ec681f3Smrg 3477ec681f3Smrg if (match) { 3487ec681f3Smrg bitmask_t m = { 0 }; 3497ec681f3Smrg BITSET_AND(m.bitset, match->dontcare.bitset, val.bitset); 3507ec681f3Smrg 3517ec681f3Smrg if (BITSET_COUNT(m.bitset)) { 3527ec681f3Smrg decode_error(state, "dontcare bits in %s: %"BITSET_FORMAT, 3537ec681f3Smrg match->name, BITSET_VALUE(m.bitset)); 3547ec681f3Smrg } 3557ec681f3Smrg } 3567ec681f3Smrg 3577ec681f3Smrg return match; 3587ec681f3Smrg} 3597ec681f3Smrg 3607ec681f3Smrgstatic const struct isa_field * 3617ec681f3Smrgfind_field(struct decode_scope *scope, const struct isa_bitset *bitset, 3627ec681f3Smrg const char *name, size_t name_len) 3637ec681f3Smrg{ 3647ec681f3Smrg for (unsigned i = 0; i < bitset->num_cases; i++) { 3657ec681f3Smrg const struct isa_case *c = bitset->cases[i]; 3667ec681f3Smrg 3677ec681f3Smrg if (c->expr) { 3687ec681f3Smrg struct decode_state *state = scope->state; 3697ec681f3Smrg 3707ec681f3Smrg /* When resolving a field for evaluating an expression, 3717ec681f3Smrg * temporarily assume the expression evaluates to true. 3727ec681f3Smrg * This allows <override/>'s to speculatively refer to 3737ec681f3Smrg * fields defined within the override: 3747ec681f3Smrg */ 3757ec681f3Smrg isa_expr_t cur_expr = NULL; 3767ec681f3Smrg if (state->expr_sp > 0) 3777ec681f3Smrg cur_expr = state->expr_stack[state->expr_sp - 1]; 3787ec681f3Smrg if ((cur_expr != c->expr) && !evaluate_expr(scope, c->expr)) 3797ec681f3Smrg continue; 3807ec681f3Smrg } 3817ec681f3Smrg 3827ec681f3Smrg for (unsigned i = 0; i < c->num_fields; i++) { 3837ec681f3Smrg if (!strncmp(name, c->fields[i].name, name_len) && 3847ec681f3Smrg (c->fields[i].name[name_len] == '\0')) { 3857ec681f3Smrg return &c->fields[i]; 3867ec681f3Smrg } 3877ec681f3Smrg } 3887ec681f3Smrg } 3897ec681f3Smrg 3907ec681f3Smrg if (bitset->parent) { 3917ec681f3Smrg const struct isa_field *f = find_field(scope, bitset->parent, name, name_len); 3927ec681f3Smrg if (f) { 3937ec681f3Smrg return f; 3947ec681f3Smrg } 3957ec681f3Smrg } 3967ec681f3Smrg 3977ec681f3Smrg return NULL; 3987ec681f3Smrg} 3997ec681f3Smrg 4007ec681f3Smrgstatic bitmask_t 4017ec681f3Smrgextract_field(struct decode_scope *scope, const struct isa_field *field) 4027ec681f3Smrg{ 4037ec681f3Smrg bitmask_t val, mask; 4047ec681f3Smrg 4057ec681f3Smrg BITSET_COPY(val.bitset, scope->val.bitset); 4067ec681f3Smrg BITSET_ZERO(mask.bitset); 4077ec681f3Smrg 4087ec681f3Smrg BITSET_SET_RANGE(mask.bitset, field->low, field->high); 4097ec681f3Smrg BITSET_AND(val.bitset, val.bitset, mask.bitset); 4107ec681f3Smrg BITSET_SHR(val.bitset, field->low); 4117ec681f3Smrg 4127ec681f3Smrg return val; 4137ec681f3Smrg} 4147ec681f3Smrg 4157ec681f3Smrg/** 4167ec681f3Smrg * Find the display template for a given bitset, recursively searching 4177ec681f3Smrg * parents in the bitset hierarchy. 4187ec681f3Smrg */ 4197ec681f3Smrgstatic const char * 4207ec681f3Smrgfind_display(struct decode_scope *scope, const struct isa_bitset *bitset) 4217ec681f3Smrg{ 4227ec681f3Smrg for (unsigned i = 0; i < bitset->num_cases; i++) { 4237ec681f3Smrg const struct isa_case *c = bitset->cases[i]; 4247ec681f3Smrg if (c->expr && !evaluate_expr(scope, c->expr)) 4257ec681f3Smrg continue; 4267ec681f3Smrg /* since this is the chosen case, it seems like a good place 4277ec681f3Smrg * to check asserted bits: 4287ec681f3Smrg */ 4297ec681f3Smrg for (unsigned j = 0; j < c->num_fields; j++) { 4307ec681f3Smrg if (c->fields[j].type == TYPE_ASSERT) { 4317ec681f3Smrg const struct isa_field *f = &c->fields[j]; 4327ec681f3Smrg bitmask_t val; 4337ec681f3Smrg 4347ec681f3Smrg val = extract_field(scope, f); 4357ec681f3Smrg if (!BITSET_EQUAL(val.bitset, f->val.bitset)) { 4367ec681f3Smrg decode_error(scope->state, "WARNING: unexpected " 4377ec681f3Smrg "bits[%u:%u] in %s: %"BITSET_FORMAT" vs %"BITSET_FORMAT, 4387ec681f3Smrg f->low, f->high, bitset->name, 4397ec681f3Smrg BITSET_VALUE(val.bitset), BITSET_VALUE(f->val.bitset)); 4407ec681f3Smrg } 4417ec681f3Smrg } 4427ec681f3Smrg } 4437ec681f3Smrg if (!c->display) 4447ec681f3Smrg continue; 4457ec681f3Smrg return c->display; 4467ec681f3Smrg } 4477ec681f3Smrg 4487ec681f3Smrg /** 4497ec681f3Smrg * If we didn't find something check up the bitset hierarchy. 4507ec681f3Smrg */ 4517ec681f3Smrg if (bitset->parent) { 4527ec681f3Smrg return find_display(scope, bitset->parent); 4537ec681f3Smrg } 4547ec681f3Smrg 4557ec681f3Smrg return NULL; 4567ec681f3Smrg} 4577ec681f3Smrg 4587ec681f3Smrg/** 4597ec681f3Smrg * Decode a field that is itself another bitset type 4607ec681f3Smrg */ 4617ec681f3Smrgstatic void 4627ec681f3Smrgdisplay_bitset_field(struct decode_scope *scope, const struct isa_field *field, bitmask_t val) 4637ec681f3Smrg{ 4647ec681f3Smrg const struct isa_bitset *b = find_bitset(scope->state, field->bitsets, val); 4657ec681f3Smrg if (!b) { 4667ec681f3Smrg decode_error(scope->state, "no match: FIELD: '%s.%s': %"BITSET_FORMAT, 4677ec681f3Smrg scope->bitset->name, field->name, BITSET_VALUE(val.bitset)); 4687ec681f3Smrg return; 4697ec681f3Smrg } 4707ec681f3Smrg 4717ec681f3Smrg struct decode_scope *nested_scope = 4727ec681f3Smrg push_scope(scope->state, b, val); 4737ec681f3Smrg nested_scope->params = field->params; 4747ec681f3Smrg display(nested_scope); 4757ec681f3Smrg pop_scope(nested_scope); 4767ec681f3Smrg} 4777ec681f3Smrg 4787ec681f3Smrgstatic void 4797ec681f3Smrgdisplay_enum_field(struct decode_scope *scope, const struct isa_field *field, bitmask_t val) 4807ec681f3Smrg{ 4817ec681f3Smrg const struct isa_enum *e = field->enums; 4827ec681f3Smrg const uint64_t ui = bitmask_to_uint64_t(val); 4837ec681f3Smrg 4847ec681f3Smrg for (unsigned i = 0; i < e->num_values; i++) { 4857ec681f3Smrg if (e->values[i].val == ui) { 4867ec681f3Smrg print(scope->state, "%s", e->values[i].display); 4877ec681f3Smrg return; 4887ec681f3Smrg } 4897ec681f3Smrg } 4907ec681f3Smrg 4917ec681f3Smrg print(scope->state, "%u", (unsigned)ui); 4927ec681f3Smrg} 4937ec681f3Smrg 4947ec681f3Smrgstatic const struct isa_field * 4957ec681f3Smrgresolve_field(struct decode_scope *scope, const char *field_name, size_t field_name_len, bitmask_t *valp) 4967ec681f3Smrg{ 4977ec681f3Smrg if (!scope) { 4987ec681f3Smrg /* We've reached the bottom of the stack! */ 4997ec681f3Smrg return NULL; 5007ec681f3Smrg } 5017ec681f3Smrg 5027ec681f3Smrg const struct isa_field *field = 5037ec681f3Smrg find_field(scope, scope->bitset, field_name, field_name_len); 5047ec681f3Smrg 5057ec681f3Smrg if (!field && scope->params) { 5067ec681f3Smrg for (unsigned i = 0; i < scope->params->num_params; i++) { 5077ec681f3Smrg if (!strncmp(field_name, scope->params->params[i].as, field_name_len) && 5087ec681f3Smrg (scope->params->params[i].as[field_name_len] == '\0')) { 5097ec681f3Smrg const char *param_name = scope->params->params[i].name; 5107ec681f3Smrg return resolve_field(scope->parent, param_name, strlen(param_name), valp); 5117ec681f3Smrg } 5127ec681f3Smrg } 5137ec681f3Smrg } 5147ec681f3Smrg 5157ec681f3Smrg if (!field) { 5167ec681f3Smrg return NULL; 5177ec681f3Smrg } 5187ec681f3Smrg 5197ec681f3Smrg /* extract out raw field value: */ 5207ec681f3Smrg if (field->expr) { 5217ec681f3Smrg uint64_t val = evaluate_expr(scope, field->expr); 5227ec681f3Smrg 5237ec681f3Smrg *valp = uint64_t_to_bitmask(val); 5247ec681f3Smrg } else { 5257ec681f3Smrg *valp = extract_field(scope, field); 5267ec681f3Smrg } 5277ec681f3Smrg 5287ec681f3Smrg return field; 5297ec681f3Smrg} 5307ec681f3Smrg 5317ec681f3Smrg/* This is also used from generated expr functions */ 5327ec681f3Smrguint64_t 5337ec681f3Smrgisa_decode_field(struct decode_scope *scope, const char *field_name) 5347ec681f3Smrg{ 5357ec681f3Smrg bitmask_t val; 5367ec681f3Smrg const struct isa_field *field = resolve_field(scope, field_name, strlen(field_name), &val); 5377ec681f3Smrg if (!field) { 5387ec681f3Smrg decode_error(scope->state, "no field '%s'", field_name); 5397ec681f3Smrg return 0; 5407ec681f3Smrg } 5417ec681f3Smrg 5427ec681f3Smrg return bitmask_to_uint64_t(val); 5437ec681f3Smrg} 5447ec681f3Smrg 5457ec681f3Smrgstatic void 5467ec681f3Smrgdisplay_field(struct decode_scope *scope, const char *field_name) 5477ec681f3Smrg{ 5487ec681f3Smrg const struct isa_decode_options *options = scope->state->options; 5497ec681f3Smrg struct decode_state *state = scope->state; 5507ec681f3Smrg size_t field_name_len = strlen(field_name); 5517ec681f3Smrg int num_align = 0; 5527ec681f3Smrg 5537ec681f3Smrg /* alignment handling */ 5547ec681f3Smrg const char *align = strstr(field_name, ":align="); 5557ec681f3Smrg 5567ec681f3Smrg if (align) { 5577ec681f3Smrg const char *value = strstr(align, "=") + 1; 5587ec681f3Smrg 5597ec681f3Smrg field_name_len = align - field_name; 5607ec681f3Smrg num_align = atoi(value); 5617ec681f3Smrg } 5627ec681f3Smrg 5637ec681f3Smrg /* Special case 'NAME' maps to instruction/bitset name: */ 5647ec681f3Smrg if (!strncmp("NAME", field_name, field_name_len)) { 5657ec681f3Smrg if (options->field_cb) { 5667ec681f3Smrg options->field_cb(options->cbdata, field_name, &(struct isa_decode_value){ 5677ec681f3Smrg .str = scope->bitset->name, 5687ec681f3Smrg }); 5697ec681f3Smrg } 5707ec681f3Smrg 5717ec681f3Smrg while (scope->state->line_column < num_align) 5727ec681f3Smrg print(state, " "); 5737ec681f3Smrg 5747ec681f3Smrg print(scope->state, "%s", scope->bitset->name); 5757ec681f3Smrg 5767ec681f3Smrg return; 5777ec681f3Smrg } 5787ec681f3Smrg 5797ec681f3Smrg bitmask_t v; 5807ec681f3Smrg const struct isa_field *field = resolve_field(scope, field_name, field_name_len, &v); 5817ec681f3Smrg if (!field) { 5827ec681f3Smrg decode_error(scope->state, "no field '%.*s'", (int)field_name_len, field_name); 5837ec681f3Smrg return; 5847ec681f3Smrg } 5857ec681f3Smrg 5867ec681f3Smrg uint64_t val = bitmask_to_uint64_t(v); 5877ec681f3Smrg 5887ec681f3Smrg if (options->field_cb) { 5897ec681f3Smrg options->field_cb(options->cbdata, field_name, &(struct isa_decode_value){ 5907ec681f3Smrg .num = val, 5917ec681f3Smrg }); 5927ec681f3Smrg } 5937ec681f3Smrg 5947ec681f3Smrg unsigned width = 1 + field->high - field->low; 5957ec681f3Smrg 5967ec681f3Smrg while (scope->state->line_column < num_align) 5977ec681f3Smrg print(state, " "); 5987ec681f3Smrg 5997ec681f3Smrg switch (field->type) { 6007ec681f3Smrg /* Basic types: */ 6017ec681f3Smrg case TYPE_BRANCH: 6027ec681f3Smrg if (scope->state->options->branch_labels) { 6037ec681f3Smrg int offset = util_sign_extend(val, width) + scope->state->n; 6047ec681f3Smrg if (offset < scope->state->num_instr) { 6057ec681f3Smrg print(scope->state, "l%d", offset); 6067ec681f3Smrg BITSET_SET(scope->state->branch_targets, offset); 6077ec681f3Smrg break; 6087ec681f3Smrg } 6097ec681f3Smrg } 6107ec681f3Smrg FALLTHROUGH; 6117ec681f3Smrg case TYPE_INT: 6127ec681f3Smrg print(scope->state, "%"PRId64, util_sign_extend(val, width)); 6137ec681f3Smrg break; 6147ec681f3Smrg case TYPE_UINT: 6157ec681f3Smrg print(scope->state, "%"PRIu64, val); 6167ec681f3Smrg break; 6177ec681f3Smrg case TYPE_HEX: 6187ec681f3Smrg // TODO format # of digits based on field width? 6197ec681f3Smrg print(scope->state, "%"PRIx64, val); 6207ec681f3Smrg break; 6217ec681f3Smrg case TYPE_OFFSET: 6227ec681f3Smrg if (val != 0) { 6237ec681f3Smrg print(scope->state, "%+"PRId64, util_sign_extend(val, width)); 6247ec681f3Smrg } 6257ec681f3Smrg break; 6267ec681f3Smrg case TYPE_UOFFSET: 6277ec681f3Smrg if (val != 0) { 6287ec681f3Smrg print(scope->state, "+%"PRIu64, val); 6297ec681f3Smrg } 6307ec681f3Smrg break; 6317ec681f3Smrg case TYPE_FLOAT: 6327ec681f3Smrg if (width == 16) { 6337ec681f3Smrg print(scope->state, "%f", _mesa_half_to_float(val)); 6347ec681f3Smrg } else { 6357ec681f3Smrg assert(width == 32); 6367ec681f3Smrg print(scope->state, "%f", uif(val)); 6377ec681f3Smrg } 6387ec681f3Smrg break; 6397ec681f3Smrg case TYPE_BOOL: 6407ec681f3Smrg if (field->display) { 6417ec681f3Smrg if (val) { 6427ec681f3Smrg print(scope->state, "%s", field->display); 6437ec681f3Smrg } 6447ec681f3Smrg } else { 6457ec681f3Smrg print(scope->state, "%u", (unsigned)val); 6467ec681f3Smrg } 6477ec681f3Smrg break; 6487ec681f3Smrg case TYPE_ENUM: 6497ec681f3Smrg display_enum_field(scope, field, v); 6507ec681f3Smrg break; 6517ec681f3Smrg 6527ec681f3Smrg case TYPE_ASSERT: 6537ec681f3Smrg /* assert fields are not for display */ 6547ec681f3Smrg assert(0); 6557ec681f3Smrg break; 6567ec681f3Smrg 6577ec681f3Smrg /* For fields that are decoded with another bitset hierarchy: */ 6587ec681f3Smrg case TYPE_BITSET: 6597ec681f3Smrg display_bitset_field(scope, field, v); 6607ec681f3Smrg break; 6617ec681f3Smrg default: 6627ec681f3Smrg decode_error(scope->state, "Bad field type: %d (%s)", 6637ec681f3Smrg field->type, field->name); 6647ec681f3Smrg } 6657ec681f3Smrg} 6667ec681f3Smrg 6677ec681f3Smrgstatic void 6687ec681f3Smrgdisplay(struct decode_scope *scope) 6697ec681f3Smrg{ 6707ec681f3Smrg const struct isa_bitset *bitset = scope->bitset; 6717ec681f3Smrg const char *display = find_display(scope, bitset); 6727ec681f3Smrg 6737ec681f3Smrg if (!display) { 6747ec681f3Smrg decode_error(scope->state, "%s: no display template", bitset->name); 6757ec681f3Smrg return; 6767ec681f3Smrg } 6777ec681f3Smrg 6787ec681f3Smrg const char *p = display; 6797ec681f3Smrg 6807ec681f3Smrg while (*p != '\0') { 6817ec681f3Smrg if (*p == '{') { 6827ec681f3Smrg const char *e = ++p; 6837ec681f3Smrg while (*e != '}') { 6847ec681f3Smrg e++; 6857ec681f3Smrg } 6867ec681f3Smrg 6877ec681f3Smrg char *field_name = strndup(p, e-p); 6887ec681f3Smrg display_field(scope, field_name); 6897ec681f3Smrg free(field_name); 6907ec681f3Smrg 6917ec681f3Smrg p = e; 6927ec681f3Smrg } else { 6937ec681f3Smrg fputc(*p, scope->state->out); 6947ec681f3Smrg scope->state->line_column++; 6957ec681f3Smrg } 6967ec681f3Smrg p++; 6977ec681f3Smrg } 6987ec681f3Smrg} 6997ec681f3Smrg 7007ec681f3Smrgstatic void 7017ec681f3Smrgdecode(struct decode_state *state, void *bin, int sz) 7027ec681f3Smrg{ 7037ec681f3Smrg BITSET_WORD *instrs = bin; 7047ec681f3Smrg unsigned errors = 0; /* number of consecutive unmatched instructions */ 7057ec681f3Smrg 7067ec681f3Smrg assert(sz % BITMASK_WORDS == 0); 7077ec681f3Smrg 7087ec681f3Smrg for (state->n = 0; state->n < state->num_instr; state->n++) { 7097ec681f3Smrg bitmask_t instr = { 0 }; 7107ec681f3Smrg 7117ec681f3Smrg next_instruction(&instr, &instrs[state->n * BITMASK_WORDS]); 7127ec681f3Smrg state->line_column = 0; 7137ec681f3Smrg 7147ec681f3Smrg if (state->options->max_errors && (errors > state->options->max_errors)) { 7157ec681f3Smrg break; 7167ec681f3Smrg } 7177ec681f3Smrg 7187ec681f3Smrg if (state->options->branch_labels && 7197ec681f3Smrg BITSET_TEST(state->branch_targets, state->n)) { 7207ec681f3Smrg if (state->options->instr_cb) { 7217ec681f3Smrg state->options->instr_cb(state->options->cbdata, 7227ec681f3Smrg state->n, instr.bitset); 7237ec681f3Smrg } 7247ec681f3Smrg print(state, "l%d:\n", state->n); 7257ec681f3Smrg } 7267ec681f3Smrg 7277ec681f3Smrg if (state->options->instr_cb) { 7287ec681f3Smrg state->options->instr_cb(state->options->cbdata, state->n, instr.bitset); 7297ec681f3Smrg } 7307ec681f3Smrg 7317ec681f3Smrg const struct isa_bitset *b = find_bitset(state, __instruction, instr); 7327ec681f3Smrg if (!b) { 7337ec681f3Smrg print(state, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset)); 7347ec681f3Smrg errors++; 7357ec681f3Smrg continue; 7367ec681f3Smrg } 7377ec681f3Smrg 7387ec681f3Smrg struct decode_scope *scope = push_scope(state, b, instr); 7397ec681f3Smrg 7407ec681f3Smrg display(scope); 7417ec681f3Smrg if (flush_errors(state)) { 7427ec681f3Smrg errors++; 7437ec681f3Smrg } else { 7447ec681f3Smrg errors = 0; 7457ec681f3Smrg } 7467ec681f3Smrg print(state, "\n"); 7477ec681f3Smrg 7487ec681f3Smrg pop_scope(scope); 7497ec681f3Smrg 7507ec681f3Smrg if (state->options->stop) { 7517ec681f3Smrg break; 7527ec681f3Smrg } 7537ec681f3Smrg } 7547ec681f3Smrg} 7557ec681f3Smrg 7567ec681f3Smrgvoid 7577ec681f3Smrgisa_decode(void *bin, int sz, FILE *out, const struct isa_decode_options *options) 7587ec681f3Smrg{ 7597ec681f3Smrg const struct isa_decode_options default_options = { 7607ec681f3Smrg .branch_labels = options ? options->branch_labels : false 7617ec681f3Smrg }; 7627ec681f3Smrg struct decode_state *state; 7637ec681f3Smrg 7647ec681f3Smrg if (!options) 7657ec681f3Smrg options = &default_options; 7667ec681f3Smrg 7677ec681f3Smrg util_cpu_detect(); /* needed for _mesa_half_to_float() */ 7687ec681f3Smrg 7697ec681f3Smrg state = rzalloc_size(NULL, sizeof(*state)); 7707ec681f3Smrg state->options = options; 7717ec681f3Smrg state->num_instr = sz / (BITMASK_WORDS * sizeof(BITSET_WORD)); 7727ec681f3Smrg 7737ec681f3Smrg if (state->options->branch_labels) { 7747ec681f3Smrg state->branch_targets = rzalloc_size(state, 7757ec681f3Smrg sizeof(BITSET_WORD) * BITSET_WORDS(state->num_instr)); 7767ec681f3Smrg 7777ec681f3Smrg /* Do a pre-pass to find all the branch targets: */ 7787ec681f3Smrg state->out = fopen("/dev/null", "w"); 7797ec681f3Smrg state->options = &default_options; /* skip hooks for prepass */ 7807ec681f3Smrg decode(state, bin, sz); 7817ec681f3Smrg fclose(state->out); 7827ec681f3Smrg if (options) { 7837ec681f3Smrg state->options = options; 7847ec681f3Smrg } 7857ec681f3Smrg } 7867ec681f3Smrg 7877ec681f3Smrg state->out = out; 7887ec681f3Smrg 7897ec681f3Smrg decode(state, bin, sz); 7907ec681f3Smrg 7917ec681f3Smrg ralloc_free(state); 7927ec681f3Smrg} 793