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