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