1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Google, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <inttypes.h>
26bf215546Sopenharmony_ci#include <stdbool.h>
27bf215546Sopenharmony_ci#include <stdint.h>
28bf215546Sopenharmony_ci#include <stdio.h>
29bf215546Sopenharmony_ci#include <stdlib.h>
30bf215546Sopenharmony_ci#include <string.h>
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/bitset.h"
33bf215546Sopenharmony_ci#include "util/compiler.h"
34bf215546Sopenharmony_ci#include "util/half_float.h"
35bf215546Sopenharmony_ci#include "util/hash_table.h"
36bf215546Sopenharmony_ci#include "util/ralloc.h"
37bf215546Sopenharmony_ci#include "util/u_debug.h"
38bf215546Sopenharmony_ci#include "util/u_math.h"
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci#include "decode.h"
41bf215546Sopenharmony_ci#include "isa.h"
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci/**
44bf215546Sopenharmony_ci * The set of leaf node bitsets in the bitset hiearchy which defines all
45bf215546Sopenharmony_ci * the possible instructions.
46bf215546Sopenharmony_ci *
47bf215546Sopenharmony_ci * TODO maybe we want to pass this in as parameter so this same decoder
48bf215546Sopenharmony_ci * can work with multiple different instruction sets.
49bf215546Sopenharmony_ci */
50bf215546Sopenharmony_ciextern const struct isa_bitset *__instruction[];
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_cistruct decode_state;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci/**
55bf215546Sopenharmony_ci * Decode scope.  When parsing a field that is itself a bitset, we push a
56bf215546Sopenharmony_ci * new scope to the stack.  A nested bitset is allowed to resolve fields
57bf215546Sopenharmony_ci * from an enclosing scope (needed, for example, to decode src register
58bf215546Sopenharmony_ci * bitsets, where half/fullness is determined by fields outset if bitset
59bf215546Sopenharmony_ci * in the instruction containing the bitset.
60bf215546Sopenharmony_ci *
61bf215546Sopenharmony_ci * But the field being resolved could be a derived field, or different
62bf215546Sopenharmony_ci * depending on an override at a higher level of the stack, requiring
63bf215546Sopenharmony_ci * expression evaluation which could in turn reference variables which
64bf215546Sopenharmony_ci * triggers a recursive field lookup.  But those lookups should not start
65bf215546Sopenharmony_ci * from the top of the stack, but instead the current stack level.  This
66bf215546Sopenharmony_ci * prevents a field from accidentally resolving to different values
67bf215546Sopenharmony_ci * depending on the starting point of the lookup.  (Not only causing
68bf215546Sopenharmony_ci * confusion, but this is behavior we don't want to depend on if we
69bf215546Sopenharmony_ci * wanted to optimize things by caching field lookup results.)
70bf215546Sopenharmony_ci */
71bf215546Sopenharmony_cistruct decode_scope {
72bf215546Sopenharmony_ci	/**
73bf215546Sopenharmony_ci	 * Enclosing scope
74bf215546Sopenharmony_ci	 */
75bf215546Sopenharmony_ci	struct decode_scope *parent;
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci	/**
78bf215546Sopenharmony_ci	 * Current bitset value being decoded
79bf215546Sopenharmony_ci	 */
80bf215546Sopenharmony_ci	bitmask_t val;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci	/**
83bf215546Sopenharmony_ci	 * Current bitset.
84bf215546Sopenharmony_ci	 */
85bf215546Sopenharmony_ci	const struct isa_bitset *bitset;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci	/**
88bf215546Sopenharmony_ci	 * Field name remapping.
89bf215546Sopenharmony_ci	 */
90bf215546Sopenharmony_ci	const struct isa_field_params *params;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci	/**
93bf215546Sopenharmony_ci	 * Pointer back to decode state, for convenience.
94bf215546Sopenharmony_ci	 */
95bf215546Sopenharmony_ci	struct decode_state *state;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci	/**
98bf215546Sopenharmony_ci	 * Cache expression evaluation results.  Expressions for overrides can
99bf215546Sopenharmony_ci	 * be repeatedly evaluated for each field being resolved.  And each
100bf215546Sopenharmony_ci	 * field reference to a derived field (potentially from another expr)
101bf215546Sopenharmony_ci	 * would require re-evaluation.  But for a given scope, each evaluation
102bf215546Sopenharmony_ci	 * of an expression gives the same result.  So we can cache to speed
103bf215546Sopenharmony_ci	 * things up.
104bf215546Sopenharmony_ci	 *
105bf215546Sopenharmony_ci	 * TODO we could maybe be clever and assign a unique idx to each expr
106bf215546Sopenharmony_ci	 * and use a direct lookup table?  Would be a bit more clever if it was
107bf215546Sopenharmony_ci	 * smart enough to allow unrelated expressions that are never involved
108bf215546Sopenharmony_ci	 * in a given scope to have overlapping cache lookup idx's.
109bf215546Sopenharmony_ci	 */
110bf215546Sopenharmony_ci	struct hash_table *cache;
111bf215546Sopenharmony_ci};
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci/**
114bf215546Sopenharmony_ci * Current decode state
115bf215546Sopenharmony_ci */
116bf215546Sopenharmony_cistruct decode_state {
117bf215546Sopenharmony_ci	const struct isa_decode_options *options;
118bf215546Sopenharmony_ci	FILE *out;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci	/**
121bf215546Sopenharmony_ci	 * Current instruction being decoded:
122bf215546Sopenharmony_ci	 */
123bf215546Sopenharmony_ci	unsigned n;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci	/**
126bf215546Sopenharmony_ci	 * Number of instructions being decoded
127bf215546Sopenharmony_ci	 */
128bf215546Sopenharmony_ci	unsigned num_instr;
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci	/**
131bf215546Sopenharmony_ci	 * Column number of current line
132bf215546Sopenharmony_ci	 */
133bf215546Sopenharmony_ci	unsigned line_column;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci	/**
136bf215546Sopenharmony_ci	 * Bitset of instructions that are branch targets (if options->branch_labels
137bf215546Sopenharmony_ci	 * is enabled)
138bf215546Sopenharmony_ci	 */
139bf215546Sopenharmony_ci	BITSET_WORD *branch_targets;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci	/**
142bf215546Sopenharmony_ci	 * We allow a limited amount of expression evaluation recursion, but
143bf215546Sopenharmony_ci	 * not recursive evaluation of any given expression, to prevent infinite
144bf215546Sopenharmony_ci	 * recursion.
145bf215546Sopenharmony_ci	 */
146bf215546Sopenharmony_ci	int expr_sp;
147bf215546Sopenharmony_ci	isa_expr_t expr_stack[8];
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci	/**
150bf215546Sopenharmony_ci	 * Current topmost/innermost level of scope used for decoding fields,
151bf215546Sopenharmony_ci	 * including derived fields which may in turn rely on decoding other
152bf215546Sopenharmony_ci	 * fields, potentially from a lower/out level in the stack.
153bf215546Sopenharmony_ci	 */
154bf215546Sopenharmony_ci	struct decode_scope *scope;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci	/**
157bf215546Sopenharmony_ci	 * A small fixed upper limit on # of decode errors to capture per-
158bf215546Sopenharmony_ci	 * instruction seems reasonable.
159bf215546Sopenharmony_ci	 */
160bf215546Sopenharmony_ci	unsigned num_errors;
161bf215546Sopenharmony_ci	char *errors[4];
162bf215546Sopenharmony_ci};
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_cistatic void
165bf215546Sopenharmony_ciprint(struct decode_state *state, const char *fmt, ...)
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci	char *buffer;
168bf215546Sopenharmony_ci	va_list args;
169bf215546Sopenharmony_ci	int ret;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci	va_start(args, fmt);
172bf215546Sopenharmony_ci	ret = vasprintf(&buffer, fmt, args);
173bf215546Sopenharmony_ci	va_end(args);
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci	if (ret != -1) {
176bf215546Sopenharmony_ci		const size_t len = strlen(buffer);
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci		for (size_t i = 0; i < len; i++) {
179bf215546Sopenharmony_ci			const char c = buffer[i];
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci			fputc(c, state->out);
182bf215546Sopenharmony_ci			state->line_column++;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci			if (c == '\n') {
185bf215546Sopenharmony_ci				state->line_column = 0;
186bf215546Sopenharmony_ci			}
187bf215546Sopenharmony_ci      }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci		free(buffer);
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci		return;
192bf215546Sopenharmony_ci	}
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_cistatic void display(struct decode_scope *scope);
196bf215546Sopenharmony_cistatic void decode_error(struct decode_state *state, const char *fmt, ...) _util_printf_format(2,3);
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_cistatic void
199bf215546Sopenharmony_cidecode_error(struct decode_state *state, const char *fmt, ...)
200bf215546Sopenharmony_ci{
201bf215546Sopenharmony_ci	if (!state->options->show_errors) {
202bf215546Sopenharmony_ci		return;
203bf215546Sopenharmony_ci	}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci	if (state->num_errors == ARRAY_SIZE(state->errors)) {
206bf215546Sopenharmony_ci		/* too many errors, bail */
207bf215546Sopenharmony_ci		return;
208bf215546Sopenharmony_ci	}
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci	va_list ap;
211bf215546Sopenharmony_ci	va_start(ap, fmt);
212bf215546Sopenharmony_ci	vasprintf(&state->errors[state->num_errors++], fmt, ap);
213bf215546Sopenharmony_ci	va_end(ap);
214bf215546Sopenharmony_ci}
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_cistatic unsigned
217bf215546Sopenharmony_ciflush_errors(struct decode_state *state)
218bf215546Sopenharmony_ci{
219bf215546Sopenharmony_ci	unsigned num_errors = state->num_errors;
220bf215546Sopenharmony_ci	if (num_errors > 0)
221bf215546Sopenharmony_ci		print(state, "\t; ");
222bf215546Sopenharmony_ci	for (unsigned i = 0; i < num_errors; i++) {
223bf215546Sopenharmony_ci		print(state, "%s%s", (i > 0) ? ", " : "", state->errors[i]);
224bf215546Sopenharmony_ci		free(state->errors[i]);
225bf215546Sopenharmony_ci	}
226bf215546Sopenharmony_ci	state->num_errors = 0;
227bf215546Sopenharmony_ci	return num_errors;
228bf215546Sopenharmony_ci}
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_cistatic bool
232bf215546Sopenharmony_cipush_expr(struct decode_state *state, isa_expr_t expr)
233bf215546Sopenharmony_ci{
234bf215546Sopenharmony_ci	for (int i = state->expr_sp - 1; i > 0; i--) {
235bf215546Sopenharmony_ci		if (state->expr_stack[i] == expr) {
236bf215546Sopenharmony_ci			return false;
237bf215546Sopenharmony_ci		}
238bf215546Sopenharmony_ci	}
239bf215546Sopenharmony_ci	state->expr_stack[state->expr_sp++] = expr;
240bf215546Sopenharmony_ci	return true;
241bf215546Sopenharmony_ci}
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_cistatic void
244bf215546Sopenharmony_cipop_expr(struct decode_state *state)
245bf215546Sopenharmony_ci{
246bf215546Sopenharmony_ci	assert(state->expr_sp > 0);
247bf215546Sopenharmony_ci	state->expr_sp--;
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_cistatic struct decode_scope *
251bf215546Sopenharmony_cipush_scope(struct decode_state *state, const struct isa_bitset *bitset, bitmask_t val)
252bf215546Sopenharmony_ci{
253bf215546Sopenharmony_ci	struct decode_scope *scope = rzalloc_size(state, sizeof(*scope));
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci	BITSET_COPY(scope->val.bitset, val.bitset);
256bf215546Sopenharmony_ci	scope->bitset = bitset;
257bf215546Sopenharmony_ci	scope->parent = state->scope;
258bf215546Sopenharmony_ci	scope->state  = state;
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci	state->scope = scope;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci	return scope;
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_cistatic void
266bf215546Sopenharmony_cipop_scope(struct decode_scope *scope)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci	assert(scope->state->scope == scope);  /* must be top of stack */
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci	scope->state->scope = scope->parent;
271bf215546Sopenharmony_ci	ralloc_free(scope);
272bf215546Sopenharmony_ci}
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci/**
275bf215546Sopenharmony_ci * Evaluate an expression, returning it's resulting value
276bf215546Sopenharmony_ci */
277bf215546Sopenharmony_cistatic uint64_t
278bf215546Sopenharmony_cievaluate_expr(struct decode_scope *scope, isa_expr_t expr)
279bf215546Sopenharmony_ci{
280bf215546Sopenharmony_ci	if (scope->cache) {
281bf215546Sopenharmony_ci		struct hash_entry *entry = _mesa_hash_table_search(scope->cache, expr);
282bf215546Sopenharmony_ci		if (entry) {
283bf215546Sopenharmony_ci			return *(uint64_t *)entry->data;
284bf215546Sopenharmony_ci		}
285bf215546Sopenharmony_ci	} else {
286bf215546Sopenharmony_ci		scope->cache = _mesa_pointer_hash_table_create(scope);
287bf215546Sopenharmony_ci	}
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci	if (!push_expr(scope->state, expr))
290bf215546Sopenharmony_ci		return 0;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci	uint64_t ret = expr(scope);
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci	pop_expr(scope->state);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci	uint64_t *retp = ralloc_size(scope->cache, sizeof(*retp));
297bf215546Sopenharmony_ci	*retp = ret;
298bf215546Sopenharmony_ci	_mesa_hash_table_insert(scope->cache, expr, retp);
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci	return ret;
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci/**
304bf215546Sopenharmony_ci * Find the bitset in NULL terminated bitset hiearchy root table which
305bf215546Sopenharmony_ci * matches against 'val'
306bf215546Sopenharmony_ci */
307bf215546Sopenharmony_cistatic const struct isa_bitset *
308bf215546Sopenharmony_cifind_bitset(struct decode_state *state, const struct isa_bitset **bitsets,
309bf215546Sopenharmony_ci		bitmask_t val)
310bf215546Sopenharmony_ci{
311bf215546Sopenharmony_ci	const struct isa_bitset *match = NULL;
312bf215546Sopenharmony_ci	for (int n = 0; bitsets[n]; n++) {
313bf215546Sopenharmony_ci		if (state->options->gpu_id > bitsets[n]->gen.max)
314bf215546Sopenharmony_ci			continue;
315bf215546Sopenharmony_ci		if (state->options->gpu_id < bitsets[n]->gen.min)
316bf215546Sopenharmony_ci			continue;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci		// m = (val & bitsets[n]->mask) & ~bitsets[n]->dontcare;
319bf215546Sopenharmony_ci		bitmask_t m = { 0 };
320bf215546Sopenharmony_ci		bitmask_t not_dontcare;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci		BITSET_AND(m.bitset, val.bitset, bitsets[n]->mask.bitset);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci		BITSET_COPY(not_dontcare.bitset, bitsets[n]->dontcare.bitset);
325bf215546Sopenharmony_ci		BITSET_NOT(not_dontcare.bitset);
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci		BITSET_AND(m.bitset, m.bitset, not_dontcare.bitset);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci		if (!BITSET_EQUAL(m.bitset, bitsets[n]->match.bitset)) {
330bf215546Sopenharmony_ci			continue;
331bf215546Sopenharmony_ci		}
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci		/* We should only have exactly one match
334bf215546Sopenharmony_ci		 *
335bf215546Sopenharmony_ci		 * TODO more complete/formal way to validate that any given
336bf215546Sopenharmony_ci		 * bit pattern will only have a single match?
337bf215546Sopenharmony_ci		 */
338bf215546Sopenharmony_ci		if (match) {
339bf215546Sopenharmony_ci			decode_error(state, "bitset conflict: %s vs %s", match->name,
340bf215546Sopenharmony_ci					bitsets[n]->name);
341bf215546Sopenharmony_ci			return NULL;
342bf215546Sopenharmony_ci		}
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci		match = bitsets[n];
345bf215546Sopenharmony_ci	}
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci	if (match) {
348bf215546Sopenharmony_ci		bitmask_t m = { 0 };
349bf215546Sopenharmony_ci		BITSET_AND(m.bitset, match->dontcare.bitset, val.bitset);
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci		if (BITSET_COUNT(m.bitset)) {
352bf215546Sopenharmony_ci			decode_error(state, "dontcare bits in %s: %"BITSET_FORMAT,
353bf215546Sopenharmony_ci					match->name, BITSET_VALUE(m.bitset));
354bf215546Sopenharmony_ci		}
355bf215546Sopenharmony_ci	}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci	return match;
358bf215546Sopenharmony_ci}
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_cistatic const struct isa_field *
361bf215546Sopenharmony_cifind_field(struct decode_scope *scope, const struct isa_bitset *bitset,
362bf215546Sopenharmony_ci		const char *name, size_t name_len)
363bf215546Sopenharmony_ci{
364bf215546Sopenharmony_ci	for (unsigned i = 0; i < bitset->num_cases; i++) {
365bf215546Sopenharmony_ci		const struct isa_case *c = bitset->cases[i];
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci		if (c->expr) {
368bf215546Sopenharmony_ci			struct decode_state *state = scope->state;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci			/* When resolving a field for evaluating an expression,
371bf215546Sopenharmony_ci			 * temporarily assume the expression evaluates to true.
372bf215546Sopenharmony_ci			 * This allows <override/>'s to speculatively refer to
373bf215546Sopenharmony_ci			 * fields defined within the override:
374bf215546Sopenharmony_ci			 */
375bf215546Sopenharmony_ci			isa_expr_t cur_expr = NULL;
376bf215546Sopenharmony_ci			if (state->expr_sp > 0)
377bf215546Sopenharmony_ci				cur_expr = state->expr_stack[state->expr_sp - 1];
378bf215546Sopenharmony_ci			if ((cur_expr != c->expr) && !evaluate_expr(scope, c->expr))
379bf215546Sopenharmony_ci				continue;
380bf215546Sopenharmony_ci		}
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci		for (unsigned i = 0; i < c->num_fields; i++) {
383bf215546Sopenharmony_ci			if (!strncmp(name, c->fields[i].name, name_len) &&
384bf215546Sopenharmony_ci			   (c->fields[i].name[name_len] == '\0')) {
385bf215546Sopenharmony_ci				return &c->fields[i];
386bf215546Sopenharmony_ci			}
387bf215546Sopenharmony_ci		}
388bf215546Sopenharmony_ci	}
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci	if (bitset->parent) {
391bf215546Sopenharmony_ci		const struct isa_field *f = find_field(scope, bitset->parent, name, name_len);
392bf215546Sopenharmony_ci		if (f) {
393bf215546Sopenharmony_ci			return f;
394bf215546Sopenharmony_ci		}
395bf215546Sopenharmony_ci	}
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci	return NULL;
398bf215546Sopenharmony_ci}
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_cistatic bitmask_t
401bf215546Sopenharmony_ciextract_field(struct decode_scope *scope, const struct isa_field *field)
402bf215546Sopenharmony_ci{
403bf215546Sopenharmony_ci   bitmask_t val, mask;
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   BITSET_COPY(val.bitset, scope->val.bitset);
406bf215546Sopenharmony_ci   BITSET_ZERO(mask.bitset);
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci   BITSET_SET_RANGE(mask.bitset, field->low, field->high);
409bf215546Sopenharmony_ci   BITSET_AND(val.bitset, val.bitset, mask.bitset);
410bf215546Sopenharmony_ci   BITSET_SHR(val.bitset, field->low);
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   return val;
413bf215546Sopenharmony_ci}
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci/**
416bf215546Sopenharmony_ci * Find the display template for a given bitset, recursively searching
417bf215546Sopenharmony_ci * parents in the bitset hierarchy.
418bf215546Sopenharmony_ci */
419bf215546Sopenharmony_cistatic const char *
420bf215546Sopenharmony_cifind_display(struct decode_scope *scope, const struct isa_bitset *bitset)
421bf215546Sopenharmony_ci{
422bf215546Sopenharmony_ci	for (unsigned i = 0; i < bitset->num_cases; i++) {
423bf215546Sopenharmony_ci		const struct isa_case *c = bitset->cases[i];
424bf215546Sopenharmony_ci		if (c->expr && !evaluate_expr(scope, c->expr))
425bf215546Sopenharmony_ci			continue;
426bf215546Sopenharmony_ci		/* since this is the chosen case, it seems like a good place
427bf215546Sopenharmony_ci		 * to check asserted bits:
428bf215546Sopenharmony_ci		 */
429bf215546Sopenharmony_ci		for (unsigned j = 0; j < c->num_fields; j++) {
430bf215546Sopenharmony_ci			if (c->fields[j].type == TYPE_ASSERT) {
431bf215546Sopenharmony_ci				const struct isa_field *f = &c->fields[j];
432bf215546Sopenharmony_ci				bitmask_t val;
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci				val = extract_field(scope, f);
435bf215546Sopenharmony_ci				if (!BITSET_EQUAL(val.bitset, f->val.bitset)) {
436bf215546Sopenharmony_ci					decode_error(scope->state, "WARNING: unexpected "
437bf215546Sopenharmony_ci							"bits[%u:%u] in %s: %"BITSET_FORMAT" vs %"BITSET_FORMAT,
438bf215546Sopenharmony_ci							f->low, f->high, bitset->name,
439bf215546Sopenharmony_ci							BITSET_VALUE(val.bitset), BITSET_VALUE(f->val.bitset));
440bf215546Sopenharmony_ci				}
441bf215546Sopenharmony_ci			}
442bf215546Sopenharmony_ci		}
443bf215546Sopenharmony_ci		if (!c->display)
444bf215546Sopenharmony_ci			continue;
445bf215546Sopenharmony_ci		return c->display;
446bf215546Sopenharmony_ci	}
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci	/**
449bf215546Sopenharmony_ci	 * If we didn't find something check up the bitset hierarchy.
450bf215546Sopenharmony_ci	 */
451bf215546Sopenharmony_ci	if (bitset->parent) {
452bf215546Sopenharmony_ci		return find_display(scope, bitset->parent);
453bf215546Sopenharmony_ci	}
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci	return NULL;
456bf215546Sopenharmony_ci}
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci/**
459bf215546Sopenharmony_ci * Decode a field that is itself another bitset type
460bf215546Sopenharmony_ci */
461bf215546Sopenharmony_cistatic void
462bf215546Sopenharmony_cidisplay_bitset_field(struct decode_scope *scope, const struct isa_field *field, bitmask_t val)
463bf215546Sopenharmony_ci{
464bf215546Sopenharmony_ci	const struct isa_bitset *b = find_bitset(scope->state, field->bitsets, val);
465bf215546Sopenharmony_ci	if (!b) {
466bf215546Sopenharmony_ci		decode_error(scope->state, "no match: FIELD: '%s.%s': %"BITSET_FORMAT,
467bf215546Sopenharmony_ci				scope->bitset->name, field->name, BITSET_VALUE(val.bitset));
468bf215546Sopenharmony_ci		return;
469bf215546Sopenharmony_ci	}
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci	struct decode_scope *nested_scope =
472bf215546Sopenharmony_ci			push_scope(scope->state, b, val);
473bf215546Sopenharmony_ci	nested_scope->params = field->params;
474bf215546Sopenharmony_ci	display(nested_scope);
475bf215546Sopenharmony_ci	pop_scope(nested_scope);
476bf215546Sopenharmony_ci}
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_cistatic void
479bf215546Sopenharmony_cidisplay_enum_field(struct decode_scope *scope, const struct isa_field *field, bitmask_t val)
480bf215546Sopenharmony_ci{
481bf215546Sopenharmony_ci	const struct isa_enum *e = field->enums;
482bf215546Sopenharmony_ci	const uint64_t ui = bitmask_to_uint64_t(val);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci	for (unsigned i = 0; i < e->num_values; i++) {
485bf215546Sopenharmony_ci		if (e->values[i].val == ui) {
486bf215546Sopenharmony_ci			print(scope->state, "%s", e->values[i].display);
487bf215546Sopenharmony_ci			return;
488bf215546Sopenharmony_ci		}
489bf215546Sopenharmony_ci	}
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci	print(scope->state, "%u", (unsigned)ui);
492bf215546Sopenharmony_ci}
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_cistatic const struct isa_field *
495bf215546Sopenharmony_ciresolve_field(struct decode_scope *scope, const char *field_name, size_t field_name_len, bitmask_t *valp)
496bf215546Sopenharmony_ci{
497bf215546Sopenharmony_ci	if (!scope) {
498bf215546Sopenharmony_ci		/* We've reached the bottom of the stack! */
499bf215546Sopenharmony_ci		return NULL;
500bf215546Sopenharmony_ci	}
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci	const struct isa_field *field =
503bf215546Sopenharmony_ci			find_field(scope, scope->bitset, field_name, field_name_len);
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci	if (!field && scope->params) {
506bf215546Sopenharmony_ci		for (unsigned i = 0; i < scope->params->num_params; i++) {
507bf215546Sopenharmony_ci			if (!strncmp(field_name, scope->params->params[i].as, field_name_len) &&
508bf215546Sopenharmony_ci			   (scope->params->params[i].as[field_name_len] == '\0')) {
509bf215546Sopenharmony_ci				const char *param_name = scope->params->params[i].name;
510bf215546Sopenharmony_ci				return resolve_field(scope->parent, param_name, strlen(param_name), valp);
511bf215546Sopenharmony_ci			}
512bf215546Sopenharmony_ci		}
513bf215546Sopenharmony_ci	}
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci	if (!field) {
516bf215546Sopenharmony_ci		return NULL;
517bf215546Sopenharmony_ci	}
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci	/* extract out raw field value: */
520bf215546Sopenharmony_ci	if (field->expr) {
521bf215546Sopenharmony_ci		uint64_t val = evaluate_expr(scope, field->expr);
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci		*valp = uint64_t_to_bitmask(val);
524bf215546Sopenharmony_ci	} else {
525bf215546Sopenharmony_ci		*valp = extract_field(scope, field);
526bf215546Sopenharmony_ci	}
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci	return field;
529bf215546Sopenharmony_ci}
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci/* This is also used from generated expr functions */
532bf215546Sopenharmony_ciuint64_t
533bf215546Sopenharmony_ciisa_decode_field(struct decode_scope *scope, const char *field_name)
534bf215546Sopenharmony_ci{
535bf215546Sopenharmony_ci	bitmask_t val;
536bf215546Sopenharmony_ci	const struct isa_field *field = resolve_field(scope, field_name, strlen(field_name), &val);
537bf215546Sopenharmony_ci	if (!field) {
538bf215546Sopenharmony_ci		decode_error(scope->state, "no field '%s'", field_name);
539bf215546Sopenharmony_ci		return 0;
540bf215546Sopenharmony_ci	}
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci	return bitmask_to_uint64_t(val);
543bf215546Sopenharmony_ci}
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_cistatic void
546bf215546Sopenharmony_cidisplay_field(struct decode_scope *scope, const char *field_name)
547bf215546Sopenharmony_ci{
548bf215546Sopenharmony_ci	const struct isa_decode_options *options = scope->state->options;
549bf215546Sopenharmony_ci	struct decode_state *state = scope->state;
550bf215546Sopenharmony_ci	size_t field_name_len = strlen(field_name);
551bf215546Sopenharmony_ci	int num_align = 0;
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci	/* alignment handling */
554bf215546Sopenharmony_ci	const char *align = strstr(field_name, ":align=");
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci	if (align) {
557bf215546Sopenharmony_ci		const char *value = strstr(align, "=") + 1;
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci		field_name_len = align - field_name;
560bf215546Sopenharmony_ci		num_align = atoi(value);
561bf215546Sopenharmony_ci	}
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci	/* Special case ':algin=' should only do alignment */
564bf215546Sopenharmony_ci	if (field_name == align) {
565bf215546Sopenharmony_ci		while (scope->state->line_column < num_align)
566bf215546Sopenharmony_ci			print(state, " ");
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci		return;
569bf215546Sopenharmony_ci	}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci	/* Special case 'NAME' maps to instruction/bitset name: */
572bf215546Sopenharmony_ci	if (!strncmp("NAME", field_name, field_name_len)) {
573bf215546Sopenharmony_ci		if (options->field_cb) {
574bf215546Sopenharmony_ci			options->field_cb(options->cbdata, field_name, &(struct isa_decode_value){
575bf215546Sopenharmony_ci				.str = scope->bitset->name,
576bf215546Sopenharmony_ci			});
577bf215546Sopenharmony_ci		}
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci		while (scope->state->line_column < num_align)
580bf215546Sopenharmony_ci			print(state, " ");
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci		print(scope->state, "%s", scope->bitset->name);
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci		return;
585bf215546Sopenharmony_ci	}
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci	bitmask_t v;
588bf215546Sopenharmony_ci	const struct isa_field *field = resolve_field(scope, field_name, field_name_len, &v);
589bf215546Sopenharmony_ci	if (!field) {
590bf215546Sopenharmony_ci		decode_error(scope->state, "no field '%.*s'", (int)field_name_len, field_name);
591bf215546Sopenharmony_ci		return;
592bf215546Sopenharmony_ci	}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci	uint64_t val = bitmask_to_uint64_t(v);
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ci	if (options->field_cb) {
597bf215546Sopenharmony_ci		options->field_cb(options->cbdata, field_name, &(struct isa_decode_value){
598bf215546Sopenharmony_ci			.num = val,
599bf215546Sopenharmony_ci		});
600bf215546Sopenharmony_ci	}
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci	unsigned width = 1 + field->high - field->low;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci	while (scope->state->line_column < num_align)
605bf215546Sopenharmony_ci		print(state, " ");
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci	switch (field->type) {
608bf215546Sopenharmony_ci	/* Basic types: */
609bf215546Sopenharmony_ci	case TYPE_BRANCH:
610bf215546Sopenharmony_ci		if (scope->state->options->branch_labels) {
611bf215546Sopenharmony_ci			int offset = util_sign_extend(val, width) + scope->state->n;
612bf215546Sopenharmony_ci			if (offset < scope->state->num_instr) {
613bf215546Sopenharmony_ci				print(scope->state, "l%d", offset);
614bf215546Sopenharmony_ci				BITSET_SET(scope->state->branch_targets, offset);
615bf215546Sopenharmony_ci				break;
616bf215546Sopenharmony_ci			}
617bf215546Sopenharmony_ci		}
618bf215546Sopenharmony_ci		FALLTHROUGH;
619bf215546Sopenharmony_ci	case TYPE_INT:
620bf215546Sopenharmony_ci		print(scope->state, "%"PRId64, util_sign_extend(val, width));
621bf215546Sopenharmony_ci		break;
622bf215546Sopenharmony_ci	case TYPE_UINT:
623bf215546Sopenharmony_ci		print(scope->state, "%"PRIu64, val);
624bf215546Sopenharmony_ci		break;
625bf215546Sopenharmony_ci	case TYPE_HEX:
626bf215546Sopenharmony_ci		// TODO format # of digits based on field width?
627bf215546Sopenharmony_ci		print(scope->state, "%"PRIx64, val);
628bf215546Sopenharmony_ci		break;
629bf215546Sopenharmony_ci	case TYPE_OFFSET:
630bf215546Sopenharmony_ci		if (val != 0) {
631bf215546Sopenharmony_ci			print(scope->state, "%+"PRId64, util_sign_extend(val, width));
632bf215546Sopenharmony_ci		}
633bf215546Sopenharmony_ci		break;
634bf215546Sopenharmony_ci	case TYPE_UOFFSET:
635bf215546Sopenharmony_ci		if (val != 0) {
636bf215546Sopenharmony_ci			print(scope->state, "+%"PRIu64, val);
637bf215546Sopenharmony_ci		}
638bf215546Sopenharmony_ci		break;
639bf215546Sopenharmony_ci	case TYPE_FLOAT:
640bf215546Sopenharmony_ci		if (width == 16) {
641bf215546Sopenharmony_ci			print(scope->state, "%f", _mesa_half_to_float(val));
642bf215546Sopenharmony_ci		} else {
643bf215546Sopenharmony_ci			assert(width == 32);
644bf215546Sopenharmony_ci			print(scope->state, "%f", uif(val));
645bf215546Sopenharmony_ci		}
646bf215546Sopenharmony_ci		break;
647bf215546Sopenharmony_ci	case TYPE_BOOL:
648bf215546Sopenharmony_ci		if (field->display) {
649bf215546Sopenharmony_ci			if (val) {
650bf215546Sopenharmony_ci				print(scope->state, "%s", field->display);
651bf215546Sopenharmony_ci			}
652bf215546Sopenharmony_ci		} else {
653bf215546Sopenharmony_ci			print(scope->state, "%u", (unsigned)val);
654bf215546Sopenharmony_ci		}
655bf215546Sopenharmony_ci		break;
656bf215546Sopenharmony_ci	case TYPE_ENUM:
657bf215546Sopenharmony_ci		display_enum_field(scope, field, v);
658bf215546Sopenharmony_ci		break;
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci	case TYPE_ASSERT:
661bf215546Sopenharmony_ci		/* assert fields are not for display */
662bf215546Sopenharmony_ci		assert(0);
663bf215546Sopenharmony_ci		break;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci	/* For fields that are decoded with another bitset hierarchy: */
666bf215546Sopenharmony_ci	case TYPE_BITSET:
667bf215546Sopenharmony_ci		display_bitset_field(scope, field, v);
668bf215546Sopenharmony_ci		break;
669bf215546Sopenharmony_ci	default:
670bf215546Sopenharmony_ci		decode_error(scope->state, "Bad field type: %d (%s)",
671bf215546Sopenharmony_ci				field->type, field->name);
672bf215546Sopenharmony_ci	}
673bf215546Sopenharmony_ci}
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_cistatic void
676bf215546Sopenharmony_cidisplay(struct decode_scope *scope)
677bf215546Sopenharmony_ci{
678bf215546Sopenharmony_ci	const struct isa_bitset *bitset = scope->bitset;
679bf215546Sopenharmony_ci	const char *display = find_display(scope, bitset);
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci	if (!display) {
682bf215546Sopenharmony_ci		decode_error(scope->state, "%s: no display template", bitset->name);
683bf215546Sopenharmony_ci		return;
684bf215546Sopenharmony_ci	}
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci	const char *p = display;
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci	while (*p != '\0') {
689bf215546Sopenharmony_ci		if (*p == '{') {
690bf215546Sopenharmony_ci			const char *e = ++p;
691bf215546Sopenharmony_ci			while (*e != '}') {
692bf215546Sopenharmony_ci				e++;
693bf215546Sopenharmony_ci			}
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci			char *field_name = strndup(p, e-p);
696bf215546Sopenharmony_ci			display_field(scope, field_name);
697bf215546Sopenharmony_ci			free(field_name);
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci			p = e;
700bf215546Sopenharmony_ci		} else {
701bf215546Sopenharmony_ci			fputc(*p, scope->state->out);
702bf215546Sopenharmony_ci			scope->state->line_column++;
703bf215546Sopenharmony_ci		}
704bf215546Sopenharmony_ci		p++;
705bf215546Sopenharmony_ci	}
706bf215546Sopenharmony_ci}
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_cistatic void
709bf215546Sopenharmony_cidecode(struct decode_state *state, void *bin, int sz)
710bf215546Sopenharmony_ci{
711bf215546Sopenharmony_ci	BITSET_WORD *instrs = bin;
712bf215546Sopenharmony_ci	unsigned errors = 0;   /* number of consecutive unmatched instructions */
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci	assert(sz % BITMASK_WORDS == 0);
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci	for (state->n = 0; state->n < state->num_instr; state->n++) {
717bf215546Sopenharmony_ci		bitmask_t instr = { 0 };
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci		next_instruction(&instr, &instrs[state->n * BITMASK_WORDS]);
720bf215546Sopenharmony_ci      state->line_column = 0;
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_ci		if (state->options->max_errors && (errors > state->options->max_errors)) {
723bf215546Sopenharmony_ci			break;
724bf215546Sopenharmony_ci		}
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci		if (state->options->branch_labels &&
727bf215546Sopenharmony_ci				BITSET_TEST(state->branch_targets, state->n)) {
728bf215546Sopenharmony_ci			if (state->options->instr_cb) {
729bf215546Sopenharmony_ci				state->options->instr_cb(state->options->cbdata,
730bf215546Sopenharmony_ci						state->n, instr.bitset);
731bf215546Sopenharmony_ci			}
732bf215546Sopenharmony_ci			print(state, "l%d:\n", state->n);
733bf215546Sopenharmony_ci		}
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci		if (state->options->instr_cb) {
736bf215546Sopenharmony_ci			state->options->instr_cb(state->options->cbdata, state->n, instr.bitset);
737bf215546Sopenharmony_ci		}
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci		const struct isa_bitset *b = find_bitset(state, __instruction, instr);
740bf215546Sopenharmony_ci		if (!b) {
741bf215546Sopenharmony_ci			print(state, "no match: %"BITSET_FORMAT"\n", BITSET_VALUE(instr.bitset));
742bf215546Sopenharmony_ci			errors++;
743bf215546Sopenharmony_ci			continue;
744bf215546Sopenharmony_ci		}
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_ci		struct decode_scope *scope = push_scope(state, b, instr);
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci		display(scope);
749bf215546Sopenharmony_ci		if (flush_errors(state)) {
750bf215546Sopenharmony_ci			errors++;
751bf215546Sopenharmony_ci		} else {
752bf215546Sopenharmony_ci			errors = 0;
753bf215546Sopenharmony_ci		}
754bf215546Sopenharmony_ci		print(state, "\n");
755bf215546Sopenharmony_ci
756bf215546Sopenharmony_ci		pop_scope(scope);
757bf215546Sopenharmony_ci
758bf215546Sopenharmony_ci		if (state->options->stop) {
759bf215546Sopenharmony_ci			break;
760bf215546Sopenharmony_ci		}
761bf215546Sopenharmony_ci	}
762bf215546Sopenharmony_ci}
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_civoid
765bf215546Sopenharmony_ciisa_decode(void *bin, int sz, FILE *out, const struct isa_decode_options *options)
766bf215546Sopenharmony_ci{
767bf215546Sopenharmony_ci	const struct isa_decode_options default_options = {
768bf215546Sopenharmony_ci		.gpu_id = options ? options->gpu_id : 0,
769bf215546Sopenharmony_ci		.branch_labels = options ? options->branch_labels : false
770bf215546Sopenharmony_ci	};
771bf215546Sopenharmony_ci	struct decode_state *state;
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci	if (!options)
774bf215546Sopenharmony_ci		options = &default_options;
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci	state = rzalloc_size(NULL, sizeof(*state));
777bf215546Sopenharmony_ci	state->options = options;
778bf215546Sopenharmony_ci	state->num_instr = sz / (BITMASK_WORDS * sizeof(BITSET_WORD));
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci	if (state->options->branch_labels) {
781bf215546Sopenharmony_ci		state->branch_targets = rzalloc_size(state,
782bf215546Sopenharmony_ci				sizeof(BITSET_WORD) * BITSET_WORDS(state->num_instr));
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci		/* Do a pre-pass to find all the branch targets: */
785bf215546Sopenharmony_ci		state->out = fopen("/dev/null", "w");
786bf215546Sopenharmony_ci		state->options = &default_options;   /* skip hooks for prepass */
787bf215546Sopenharmony_ci		decode(state, bin, sz);
788bf215546Sopenharmony_ci		fclose(state->out);
789bf215546Sopenharmony_ci		if (options) {
790bf215546Sopenharmony_ci			state->options = options;
791bf215546Sopenharmony_ci		}
792bf215546Sopenharmony_ci	}
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_ci	state->out = out;
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci	decode(state, bin, sz);
797bf215546Sopenharmony_ci
798bf215546Sopenharmony_ci	ralloc_free(state);
799bf215546Sopenharmony_ci}
800