From 56ba9656bb38ce0d1448545a6d9d3ebcc39f18bf Mon Sep 17 00:00:00 2001 From: Sirisha Gandikota Date: Fri, 19 Aug 2016 12:13:25 -0700 Subject: aubinator: Fix the tool to correctly decode the DWords Several fixes have been added as part of this as listed below: 1) Fix the mask and add disassembler handling for STATE_DS, STATE_HS as the mask returned wrong values of the fields. 2) Fix the GEN_TYPE_ADDRESS/GEN_TYPE_OFFSET decoding - the address/ offset were handled the same way as the other fields and that gives the wrong values for the address/offset. 3) Decode nested/recurssive structures - Many packets contain nested structures, ex: 3DSATE_SO_BUFFER, STATE_BASE_ADDRESS, etc contain MOC structures. Previously, the aubinator printed 1 if there was a MOC structure. Now we decode the entire structure and print out its fields. 4) Print out the DWord address along with its hex value - For a better clarity of information, it is helpful to print both the address and hex value of the DWord along with the DWord count. Since the DWord0 contains the instruction code and the instruction length, it is unnecessary to print the decoded values for DWord0. This information is already available from the DWord hex value. 5) Decode the and the corresponding fields in the group- The tag can have fields of several types including structures. A group can contain one or more number of fields and this has be correctly decoded. Previously, aubinator did not decode the groups or the fields/structures inside them. Now we decode the in the instructions and structures where the fields in it repeat for any number of times specified. v2: Fix the formatting (per Matt) Make the start and end pos calculation to extract fields from a DWord more appropriate by moving %32 away from mask() method Signed-off-by: Sirisha Gandikota Acked-by: Kenneth Graunke Acked-by: Ben Widawsky --- src/intel/tools/decoder.c | 98 +++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 50 deletions(-) (limited to 'src/intel/tools/decoder.c') diff --git a/src/intel/tools/decoder.c b/src/intel/tools/decoder.c index 02944dd0062..f57be979038 100644 --- a/src/intel/tools/decoder.c +++ b/src/intel/tools/decoder.c @@ -47,45 +47,6 @@ struct gen_spec { struct gen_group *registers[256]; }; -struct gen_group { - char *name; - int nfields; - struct gen_field **fields; - - uint32_t opcode_mask; - uint32_t opcode; -}; - -struct gen_type { - enum { - GEN_TYPE_UNKNOWN, - GEN_TYPE_INT, - GEN_TYPE_UINT, - GEN_TYPE_BOOL, - GEN_TYPE_FLOAT, - GEN_TYPE_ADDRESS, - GEN_TYPE_OFFSET, - GEN_TYPE_STRUCT, - GEN_TYPE_UFIXED, - GEN_TYPE_SFIXED, - GEN_TYPE_MBO - } kind; - - /* Struct definition for GEN_TYPE_STRUCT */ - struct gen_group *gen_struct; - - /* Integer and fractional sizes for GEN_TYPE_UFIXED and GEN_TYPE_SFIXED */ - int i, f; -}; - -struct gen_field { - char *name; - int start, end; - struct gen_type type; - bool has_default; - uint32_t default_value; -}; - struct location { const char *filename; int line_number; @@ -185,9 +146,27 @@ create_group(struct parser_context *ctx, const char *name, const char **atts) if (name) group->name = xstrdup(name); + group->group_offset = 0; + group->group_count = 0; + return group; } +static void +get_group_offset_count(struct parser_context *ctx, const char *name, const char **atts, uint32_t *offset, uint32_t *count) +{ + char *p; + int i; + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "count") == 0) + *count = strtoul(atts[i + 1], &p, 0); + else if (strcmp(atts[i], "start") == 0) + *offset = strtoul(atts[i + 1], &p, 0); + } + return; +} + static inline uint64_t mask(int start, int end) { @@ -201,7 +180,18 @@ mask(int start, int end) static inline uint64_t field(uint64_t value, int start, int end) { - return (value & mask(start, end)) >> start; + /* The field values are obtained from the DWord, + * Hence, get the relative start and end positions + * by doing a %32 on the start and end positions + */ + return (value & mask(start % 32, end % 32)) >> (start % 32); +} + +static inline uint64_t +field_address(uint64_t value, int start, int end) +{ + /* no need to right shift for address/offset */ + return (value & mask(start % 32, end % 32)); } static struct gen_type @@ -247,10 +237,12 @@ create_field(struct parser_context *ctx, const char **atts) if (strcmp(atts[i], "name") == 0) field->name = xstrdup(atts[i + 1]); else if (strcmp(atts[i], "start") == 0) - field->start = strtoul(atts[i + 1], &p, 0); - else if (strcmp(atts[i], "end") == 0) - field->end = strtoul(atts[i + 1], &p, 0); - else if (strcmp(atts[i], "type") == 0) + field->start = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0); + else if (strcmp(atts[i], "end") == 0) { + field->end = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0); + if(ctx->group->group_offset) + ctx->group->group_offset = field->end+1; + } else if (strcmp(atts[i], "type") == 0) field->type = string_to_type(ctx, atts[i + 1]); else if (strcmp(atts[i], "default") == 0 && field->start >= 16 && field->end <= 31) { @@ -299,8 +291,13 @@ start_element(void *data, const char *element_name, const char **atts) strcmp(element_name, "register") == 0) { ctx->group = create_group(ctx, name, atts); } else if (strcmp(element_name, "group") == 0) { + get_group_offset_count(ctx, name, atts,&ctx->group->group_offset,&ctx->group->group_count); } else if (strcmp(element_name, "field") == 0) { - ctx->fields[ctx->nfields++] = create_field(ctx, atts); + do { + ctx->fields[ctx->nfields++] = create_field(ctx, atts); + if(ctx->group->group_count) + ctx->group->group_count--; + } while (ctx->group->group_count > 0); } else if (strcmp(element_name, "enum") == 0) { } else if (strcmp(element_name, "value") == 0) { } @@ -328,7 +325,7 @@ end_element(void *data, const char *name) group->fields[i]->end <= 31 && group->fields[i]->has_default) { group->opcode_mask |= - mask(group->fields[i]->start, group->fields[i]->end); + mask(group->fields[i]->start % 32, group->fields[i]->end % 32); group->opcode |= group->fields[i]->default_value << group->fields[i]->start; } @@ -341,6 +338,9 @@ end_element(void *data, const char *name) spec->structs[spec->nstructs++] = group; else if (strcmp(name, "register") == 0) spec->registers[spec->nregisters++] = group; + } else if (strcmp(name, "group") == 0) { + ctx->group->group_offset = 0; + ctx->group->group_count = 0; } } @@ -407,7 +407,6 @@ gen_spec_load(const char *filename) struct gen_group * gen_spec_find_instruction(struct gen_spec *spec, const uint32_t *p) { - /* FIXME: Make sure the opcodes put out are correct */ for (int i = 0; i < spec->ncommands; i++) { uint32_t opcode = *p & spec->commands[i]->opcode_mask; if (opcode == spec->commands[i]->opcode) @@ -495,12 +494,11 @@ gen_field_iterator_next(struct gen_field_iterator *iter) case GEN_TYPE_ADDRESS: case GEN_TYPE_OFFSET: snprintf(iter->value, sizeof(iter->value), - "0x%08lx", field(v.dw, f->start, f->end)); + "0x%08lx", field_address(v.dw, f->start, f->end)); break; case GEN_TYPE_STRUCT: - /* FIXME: Make iterator decode the struct recursively */ snprintf(iter->value, sizeof(iter->value), - "", f->type.gen_struct->name); + "", f->type.gen_struct->name, (f->start / 32)); break; case GEN_TYPE_UFIXED: snprintf(iter->value, sizeof(iter->value), -- cgit v1.2.3