compiler/isaspec: add alignment support

This helps to get a really nice and aligend disasm output.
Just use :align=X to define where in the line the field
should be printed.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11321>
This commit is contained in:
Christian Gmeiner 2021-07-14 23:30:59 +02:00 committed by Marge Bot
parent eae96d0c4c
commit ca0f892191
2 changed files with 57 additions and 12 deletions

View File

@ -184,6 +184,9 @@ decoding. The display template consists of references to fields (which may
be derived fields) specified as ``{FIELDNAME}`` and other characters
which are just echoed through to the resulting decoded bitset.
It is possible to define a line column alignment value per field to influence
the visual output. It needs to be pecified as ``{FIELDNAME:align=xx}``.
The ``<override>`` element will be described in the next section, but it
provides for both different decoded instruction syntax/mnemonics (when
simply providing a different display template string) as well as instruction

View File

@ -164,11 +164,32 @@ struct decode_state {
static void
print(struct decode_state *state, const char *fmt, ...)
{
char *buffer;
va_list args;
int ret;
va_start(args, fmt);
state->line_column += vfprintf(state->out, fmt, args);
ret = vasprintf(&buffer, fmt, args);
va_end(args);
if (ret != -1) {
const size_t len = strlen(buffer);
for (size_t i = 0; i < len; i++) {
const char c = buffer[i];
fputc(c, state->out);
state->line_column++;
if (c == '\n') {
state->line_column = 0;
}
}
free(buffer);
return;
}
}
static void display(struct decode_scope *scope);
@ -338,7 +359,7 @@ find_bitset(struct decode_state *state, const struct isa_bitset **bitsets,
static const struct isa_field *
find_field(struct decode_scope *scope, const struct isa_bitset *bitset,
const char *name)
const char *name, size_t name_len)
{
for (unsigned i = 0; i < bitset->num_cases; i++) {
const struct isa_case *c = bitset->cases[i];
@ -359,14 +380,15 @@ find_field(struct decode_scope *scope, const struct isa_bitset *bitset,
}
for (unsigned i = 0; i < c->num_fields; i++) {
if (!strcmp(name, c->fields[i].name)) {
if (!strncmp(name, c->fields[i].name, name_len) &&
(c->fields[i].name[name_len] == '\0')) {
return &c->fields[i];
}
}
}
if (bitset->parent) {
const struct isa_field *f = find_field(scope, bitset->parent, name);
const struct isa_field *f = find_field(scope, bitset->parent, name, name_len);
if (f) {
return f;
}
@ -470,7 +492,7 @@ display_enum_field(struct decode_scope *scope, const struct isa_field *field, bi
}
static const struct isa_field *
resolve_field(struct decode_scope *scope, const char *field_name, bitmask_t *valp)
resolve_field(struct decode_scope *scope, const char *field_name, size_t field_name_len, bitmask_t *valp)
{
if (!scope) {
/* We've reached the bottom of the stack! */
@ -478,13 +500,14 @@ resolve_field(struct decode_scope *scope, const char *field_name, bitmask_t *val
}
const struct isa_field *field =
find_field(scope, scope->bitset, field_name);
find_field(scope, scope->bitset, field_name, field_name_len);
if (!field && scope->params) {
for (unsigned i = 0; i < scope->params->num_params; i++) {
if (!strcmp(field_name, scope->params->params[i].as)) {
if (!strncmp(field_name, scope->params->params[i].as, field_name_len) &&
(scope->params->params[i].as[field_name_len] == '\0')) {
const char *param_name = scope->params->params[i].name;
return resolve_field(scope->parent, param_name, valp);
return resolve_field(scope->parent, param_name, strlen(param_name), valp);
}
}
}
@ -510,7 +533,7 @@ uint64_t
isa_decode_field(struct decode_scope *scope, const char *field_name)
{
bitmask_t val;
const struct isa_field *field = resolve_field(scope, field_name, &val);
const struct isa_field *field = resolve_field(scope, field_name, strlen(field_name), &val);
if (!field) {
decode_error(scope->state, "no field '%s'", field_name);
return 0;
@ -523,24 +546,40 @@ static void
display_field(struct decode_scope *scope, const char *field_name)
{
const struct isa_decode_options *options = scope->state->options;
struct decode_state *state = scope->state;
size_t field_name_len = strlen(field_name);
int num_align = 0;
/* alignment handling */
const char *align = strstr(field_name, ":align=");
if (align) {
const char *value = strstr(align, "=") + 1;
field_name_len = align - field_name;
num_align = atoi(value);
}
/* Special case 'NAME' maps to instruction/bitset name: */
if (!strcmp("NAME", field_name)) {
if (!strncmp("NAME", field_name, field_name_len)) {
if (options->field_cb) {
options->field_cb(options->cbdata, field_name, &(struct isa_decode_value){
.str = scope->bitset->name,
});
}
while (scope->state->line_column < num_align)
print(state, " ");
print(scope->state, "%s", scope->bitset->name);
return;
}
bitmask_t v;
const struct isa_field *field = resolve_field(scope, field_name, &v);
const struct isa_field *field = resolve_field(scope, field_name, field_name_len, &v);
if (!field) {
decode_error(scope->state, "no field '%s'", field_name);
decode_error(scope->state, "no field '%.*s'", (int)field_name_len, field_name);
return;
}
@ -554,6 +593,9 @@ display_field(struct decode_scope *scope, const char *field_name)
unsigned width = 1 + field->high - field->low;
while (scope->state->line_column < num_align)
print(state, " ");
switch (field->type) {
/* Basic types: */
case TYPE_BRANCH: