X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fcommon%2Fgen_decoder.c;h=d07962a0b971e7d61e5650e657cbb0b82d6c53f2;hb=289cb6b59aea755ef5e60c711bb91d9f66b3c2af;hp=de4c506ac7b668bf3fd485fbca2fb9cab34b9d28;hpb=f2646406939557ee1f75d6ee044447e40f92b565;p=mesa.git diff --git a/src/intel/common/gen_decoder.c b/src/intel/common/gen_decoder.c index de4c506ac7b..d07962a0b97 100644 --- a/src/intel/common/gen_decoder.c +++ b/src/intel/common/gen_decoder.c @@ -35,6 +35,7 @@ #include "gen_decoder.h" +#include "isl/isl.h" #include "genxml/genX_xml.h" #define XML_BUFFER_SIZE 4096 @@ -127,7 +128,7 @@ fail(struct location *loc, const char *msg, ...) } static void -get_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count, +get_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count, uint32_t *size, bool *variable) { for (int i = 0; atts[i]; i += 2) { @@ -150,7 +151,8 @@ static struct gen_group * create_group(struct parser_context *ctx, const char *name, const char **atts, - struct gen_group *parent) + struct gen_group *parent, + bool fixed_length) { struct gen_group *group; @@ -160,20 +162,51 @@ create_group(struct parser_context *ctx, group->spec = ctx->spec; group->variable = false; + group->fixed_length = fixed_length; + group->dword_length_field = NULL; + group->dw_length = 0; + group->engine_mask = I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER) | + I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO) | + I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY); + group->bias = 1; for (int i = 0; atts[i]; i += 2) { char *p; if (strcmp(atts[i], "length") == 0) { group->dw_length = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "bias") == 0) { + group->bias = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "engine") == 0) { + void *mem_ctx = ralloc_context(NULL); + char *tmp = ralloc_strdup(mem_ctx, atts[i + 1]); + char *save_ptr; + char *tok = strtok_r(tmp, "|", &save_ptr); + + group->engine_mask = 0; + while (tok != NULL) { + if (strcmp(tok, "render") == 0) { + group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER); + } else if (strcmp(tok, "video") == 0) { + group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO); + } else if (strcmp(tok, "blitter") == 0) { + group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY); + } else { + fprintf(stderr, "unknown engine class defined for instruction \"%s\": %s\n", name, atts[i + 1]); + } + + tok = strtok_r(NULL, "|", &save_ptr); + } + + ralloc_free(mem_ctx); } } if (parent) { group->parent = parent; - get_group_offset_count(atts, - &group->group_offset, - &group->group_count, - &group->group_size, + get_array_offset_count(atts, + &group->array_offset, + &group->array_count, + &group->array_item_size, &group->variable); } @@ -285,15 +318,18 @@ create_field(struct parser_context *ctx, const char **atts) for (int i = 0; atts[i]; i += 2) { char *p; - if (strcmp(atts[i], "name") == 0) + if (strcmp(atts[i], "name") == 0) { field->name = ralloc_strdup(field, atts[i + 1]); - else if (strcmp(atts[i], "start") == 0) + if (strcmp(field->name, "DWord Length") == 0) { + field->parent->dword_length_field = field; + } + } else if (strcmp(atts[i], "start") == 0) { field->start = strtoul(atts[i + 1], &p, 0); - else if (strcmp(atts[i], "end") == 0) { + } else if (strcmp(atts[i], "end") == 0) { field->end = strtoul(atts[i + 1], &p, 0); - } else if (strcmp(atts[i], "type") == 0) + } else if (strcmp(atts[i], "type") == 0) { field->type = string_to_type(ctx, atts[i + 1]); - else if (strcmp(atts[i], "default") == 0 && + } else if (strcmp(atts[i], "default") == 0 && field->start >= 16 && field->end <= 31) { field->has_default = true; field->default_value = strtoul(atts[i + 1], &p, 0); @@ -303,6 +339,20 @@ create_field(struct parser_context *ctx, const char **atts) return field; } +static struct gen_field * +create_array_field(struct parser_context *ctx, struct gen_group *array) +{ + struct gen_field *field; + + field = rzalloc(ctx->group, struct gen_field); + field->parent = ctx->group; + + field->array = array; + field->start = field->array->array_offset; + + return field; +} + static struct gen_value * create_value(struct parser_context *ctx, const char **atts) { @@ -320,9 +370,11 @@ create_value(struct parser_context *ctx, const char **atts) static struct gen_field * create_and_append_field(struct parser_context *ctx, - const char **atts) + const char **atts, + struct gen_group *array) { - struct gen_field *field = create_field(ctx, atts); + struct gen_field *field = array ? + create_array_field(ctx, array) : create_field(ctx, atts); struct gen_field *prev = NULL, *list = ctx->group->fields; while (list && field->start > list->start) { @@ -369,22 +421,19 @@ start_element(void *data, const char *element_name, const char **atts) minor = 0; ctx->spec->gen = gen_make_gen(major, minor); - } else if (strcmp(element_name, "instruction") == 0 || - strcmp(element_name, "struct") == 0) { - ctx->group = create_group(ctx, name, atts, NULL); + } else if (strcmp(element_name, "instruction") == 0) { + ctx->group = create_group(ctx, name, atts, NULL, false); + } else if (strcmp(element_name, "struct") == 0) { + ctx->group = create_group(ctx, name, atts, NULL, true); } else if (strcmp(element_name, "register") == 0) { - ctx->group = create_group(ctx, name, atts, NULL); + ctx->group = create_group(ctx, name, atts, NULL, true); get_register_offset(atts, &ctx->group->register_offset); } else if (strcmp(element_name, "group") == 0) { - struct gen_group *previous_group = ctx->group; - while (previous_group->next) - previous_group = previous_group->next; - - struct gen_group *group = create_group(ctx, "", atts, ctx->group); - previous_group->next = group; + struct gen_group *group = create_group(ctx, "", atts, ctx->group, false); + ctx->last_field = create_and_append_field(ctx, NULL, group); ctx->group = group; } else if (strcmp(element_name, "field") == 0) { - ctx->last_field = create_and_append_field(ctx, atts); + ctx->last_field = create_and_append_field(ctx, atts, NULL); } else if (strcmp(element_name, "enum") == 0) { ctx->enoom = create_enum(ctx, name, atts); } else if (strcmp(element_name, "value") == 0) { @@ -459,14 +508,13 @@ character_data(void *data, const XML_Char *s, int len) } static int -devinfo_to_gen(const struct gen_device_info *devinfo) +devinfo_to_gen(const struct gen_device_info *devinfo, bool x10) { - int value = 10 * devinfo->gen; - - if (devinfo->is_baytrail || devinfo->is_haswell) - value += 5; + if (devinfo->is_baytrail || devinfo->is_haswell) { + return devinfo->gen * 10 + 5; + } - return value; + return x10 ? devinfo->gen * 10 : devinfo->gen; } static uint32_t zlib_inflate(const void *compressed_data, @@ -522,14 +570,39 @@ static uint32_t _hash_uint32(const void *key) return (uint32_t) (uintptr_t) key; } +static struct gen_spec * +gen_spec_init(void) +{ + struct gen_spec *spec; + spec = rzalloc(NULL, struct gen_spec); + if (spec == NULL) + return NULL; + + spec->commands = + _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); + spec->structs = + _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); + spec->registers_by_name = + _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); + spec->registers_by_offset = + _mesa_hash_table_create(spec, _hash_uint32, _mesa_key_pointer_equal); + spec->enums = + _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); + spec->access_cache = + _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); + + return spec; +} + struct gen_spec * gen_spec_load(const struct gen_device_info *devinfo) { struct parser_context ctx; void *buf; uint8_t *text_data = NULL; - uint32_t text_offset = 0, text_length = 0, total_length; - uint32_t gen_10 = devinfo_to_gen(devinfo); + uint32_t text_offset = 0, text_length = 0; + ASSERTED uint32_t total_length; + uint32_t gen_10 = devinfo_to_gen(devinfo, true); for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) { if (genxml_files_table[i].gen_10 == gen_10) { @@ -555,21 +628,11 @@ gen_spec_load(const struct gen_device_info *devinfo) XML_SetElementHandler(ctx.parser, start_element, end_element); XML_SetCharacterDataHandler(ctx.parser, character_data); - ctx.spec = rzalloc(NULL, struct gen_spec); - - ctx.spec->commands = - _mesa_hash_table_create(ctx.spec, _mesa_hash_string, _mesa_key_string_equal); - ctx.spec->structs = - _mesa_hash_table_create(ctx.spec, _mesa_hash_string, _mesa_key_string_equal); - ctx.spec->registers_by_name = - _mesa_hash_table_create(ctx.spec, _mesa_hash_string, _mesa_key_string_equal); - ctx.spec->registers_by_offset = - _mesa_hash_table_create(ctx.spec, _hash_uint32, _mesa_key_pointer_equal); - ctx.spec->enums = - _mesa_hash_table_create(ctx.spec, _mesa_hash_string, _mesa_key_string_equal); - - ctx.spec->access_cache = - _mesa_hash_table_create(ctx.spec, _mesa_hash_string, _mesa_key_string_equal); + ctx.spec = gen_spec_init(); + if (ctx.spec == NULL) { + fprintf(stderr, "Failed to create gen_spec\n"); + return NULL; + } total_length = zlib_inflate(compress_genxmls, sizeof(compress_genxmls), @@ -598,23 +661,16 @@ gen_spec_load(const struct gen_device_info *devinfo) } struct gen_spec * -gen_spec_load_from_path(const struct gen_device_info *devinfo, - const char *path) +gen_spec_load_filename(const char *filename) { struct parser_context ctx; - size_t len, filename_len = strlen(path) + 20; - char *filename = malloc(filename_len); - void *buf; FILE *input; - - len = snprintf(filename, filename_len, "%s/gen%i.xml", - path, devinfo_to_gen(devinfo)); - assert(len < filename_len); + void *buf; + size_t len; input = fopen(filename, "r"); if (input == NULL) { fprintf(stderr, "failed to open xml description\n"); - free(filename); return NULL; } @@ -624,31 +680,37 @@ gen_spec_load_from_path(const struct gen_device_info *devinfo, if (ctx.parser == NULL) { fprintf(stderr, "failed to create parser\n"); fclose(input); - free(filename); return NULL; } XML_SetElementHandler(ctx.parser, start_element, end_element); XML_SetCharacterDataHandler(ctx.parser, character_data); ctx.loc.filename = filename; - ctx.spec = rzalloc(NULL, struct gen_spec); + + ctx.spec = gen_spec_init(); + if (ctx.spec == NULL) { + fprintf(stderr, "Failed to create gen_spec\n"); + goto end; + } do { buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE); len = fread(buf, 1, XML_BUFFER_SIZE, input); - if (len == 0) { + if (ferror(input)) { fprintf(stderr, "fread: %m\n"); - free(ctx.spec); + gen_spec_destroy(ctx.spec); ctx.spec = NULL; goto end; - } + } else if (len == 0 && feof(input)) + goto end; + if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) { fprintf(stderr, "Error parsing XML at line %ld col %ld: %s\n", XML_GetCurrentLineNumber(ctx.parser), XML_GetCurrentColumnNumber(ctx.parser), XML_ErrorString(XML_GetErrorCode(ctx.parser))); - free(ctx.spec); + gen_spec_destroy(ctx.spec); ctx.spec = NULL; goto end; } @@ -658,25 +720,52 @@ gen_spec_load_from_path(const struct gen_device_info *devinfo, XML_ParserFree(ctx.parser); fclose(input); - free(filename); + + /* free ctx.spec if genxml is empty */ + if (ctx.spec && + _mesa_hash_table_num_entries(ctx.spec->commands) == 0 && + _mesa_hash_table_num_entries(ctx.spec->structs) == 0) { + fprintf(stderr, + "Error parsing XML: empty spec.\n"); + gen_spec_destroy(ctx.spec); + return NULL; + } return ctx.spec; } +struct gen_spec * +gen_spec_load_from_path(const struct gen_device_info *devinfo, + const char *path) +{ + size_t filename_len = strlen(path) + 20; + char *filename = malloc(filename_len); + + ASSERTED size_t len = snprintf(filename, filename_len, "%s/gen%i.xml", + path, devinfo_to_gen(devinfo, false)); + assert(len < filename_len); + + struct gen_spec *spec = gen_spec_load_filename(filename); + free(filename); + + return spec; +} + void gen_spec_destroy(struct gen_spec *spec) { ralloc_free(spec); } struct gen_group * -gen_spec_find_instruction(struct gen_spec *spec, const uint32_t *p) +gen_spec_find_instruction(struct gen_spec *spec, + enum drm_i915_gem_engine_class engine, + const uint32_t *p) { - struct hash_entry *entry; - hash_table_foreach(spec->commands, entry) { struct gen_group *command = entry->data; uint32_t opcode = *p & command->opcode_mask; - if (opcode == command->opcode) + if ((command->engine_mask & I915_ENGINE_CLASS_TO_MASK(engine)) && + opcode == command->opcode) return command; } @@ -712,6 +801,17 @@ gen_group_find_field(struct gen_group *group, const char *name) int gen_group_get_length(struct gen_group *group, const uint32_t *p) { + if (group) { + if (group->fixed_length) + return group->dw_length; + else { + struct gen_field *field = group->dword_length_field; + if (field) { + return field_value(p[0], field->start, field->end) + group->bias; + } + } + } + uint32_t h = p[0]; uint32_t type = field_value(h, 29, 31); @@ -786,93 +886,161 @@ iter_more_fields(const struct gen_field_iterator *iter) } static uint32_t -iter_group_offset_bits(const struct gen_field_iterator *iter, - uint32_t group_iter) +iter_array_offset_bits(const struct gen_field_iterator *iter) +{ + if (iter->level == 0) + return 0; + + uint32_t offset = 0; + const struct gen_group *group = iter->groups[1]; + for (int level = 1; level <= iter->level; level++, group = iter->groups[level]) { + uint32_t array_idx = iter->array_iter[level]; + offset += group->array_offset + array_idx * group->array_item_size; + } + + return offset; +} + +/* Checks whether we have more items in the array to iterate, or more arrays to + * iterate through. + */ +/* descend into a non-array field */ +static void +iter_push_array(struct gen_field_iterator *iter) { - return iter->group->group_offset + (group_iter * iter->group->group_size); + assert(iter->level >= 0); + + iter->group = iter->field->array; + iter->level++; + assert(iter->level < DECODE_MAX_ARRAY_DEPTH); + iter->groups[iter->level] = iter->group; + iter->array_iter[iter->level] = 0; + + assert(iter->group->fields != NULL); /* an empty makes no sense */ + iter->field = iter->group->fields; + iter->fields[iter->level] = iter->field; } -static bool -iter_more_groups(const struct gen_field_iterator *iter) +static void +iter_pop_array(struct gen_field_iterator *iter) { - if (iter->group->variable) { - return iter_group_offset_bits(iter, iter->group_iter + 1) < - (gen_group_get_length(iter->group, iter->p) * 32); - } else { - return (iter->group_iter + 1) < iter->group->group_count || - iter->group->next != NULL; - } + assert(iter->level > 0); + + iter->level--; + iter->field = iter->fields[iter->level]; + iter->group = iter->groups[iter->level]; +} + +static void +iter_start_field(struct gen_field_iterator *iter, struct gen_field *field) +{ + iter->field = field; + iter->fields[iter->level] = field; + + while (iter->field->array) + iter_push_array(iter); + + int array_member_offset = iter_array_offset_bits(iter); + + iter->start_bit = array_member_offset + iter->field->start; + iter->end_bit = array_member_offset + iter->field->end; + iter->struct_desc = NULL; } static void -iter_advance_group(struct gen_field_iterator *iter) +iter_advance_array(struct gen_field_iterator *iter) { + assert(iter->level > 0); + int lvl = iter->level; + if (iter->group->variable) - iter->group_iter++; + iter->array_iter[lvl]++; else { - if ((iter->group_iter + 1) < iter->group->group_count) { - iter->group_iter++; - } else { - iter->group = iter->group->next; - iter->group_iter = 0; + if ((iter->array_iter[lvl] + 1) < iter->group->array_count) { + iter->array_iter[lvl]++; } } - iter->field = iter->group->fields; + iter_start_field(iter, iter->group->fields); } static bool -iter_advance_field(struct gen_field_iterator *iter) +iter_more_array_elems(const struct gen_field_iterator *iter) { - if (iter_more_fields(iter)) { - iter->field = iter->field->next; - } else { - if (!iter_more_groups(iter)) - return false; + int lvl = iter->level; + assert(lvl >= 0); - iter_advance_group(iter); + if (iter->group->variable) { + int length = gen_group_get_length(iter->group, iter->p); + assert(length >= 0 && "error the length is unknown!"); + return iter_array_offset_bits(iter) + iter->group->array_item_size < + (length * 32); + } else { + return (iter->array_iter[lvl] + 1) < iter->group->array_count; } +} - if (iter->field->name) - strncpy(iter->name, iter->field->name, sizeof(iter->name)); - else - memset(iter->name, 0, sizeof(iter->name)); +static bool +iter_advance_field(struct gen_field_iterator *iter) +{ + /* Keep looping while we either have more fields to look at, or we are + * inside a and can go up a level. + */ + while (iter_more_fields(iter) || iter->level > 0) { + if (iter_more_fields(iter)) { + iter_start_field(iter, iter->field->next); + return true; + } - int group_member_offset = iter_group_offset_bits(iter, iter->group_iter); + assert(iter->level >= 0); - iter->bit = group_member_offset + iter->field->start; - iter->struct_desc = NULL; + if (iter_more_array_elems(iter)) { + iter_advance_array(iter); + return true; + } - return true; + /* At this point, we reached the end of the and were on the last + * iteration. So it's time to go back to the parent and then advance the + * field. + */ + iter_pop_array(iter); + } + + return false; } -static uint64_t -iter_decode_field_raw(struct gen_field *field, - const uint32_t *p, - const uint32_t *end) +static bool +iter_decode_field_raw(struct gen_field_iterator *iter, uint64_t *qw) { - uint64_t qw = 0; + *qw = 0; + + int field_start = iter->p_bit + iter->start_bit; + int field_end = iter->p_bit + iter->end_bit; + + const uint32_t *p = iter->p + (iter->start_bit / 32); + if (iter->p_end && p >= iter->p_end) + return false; - if ((field->end - field->start) > 32) { - if ((p + 1) < end) - qw = ((uint64_t) p[1]) << 32; - qw |= p[0]; + if ((field_end - field_start) > 32) { + if (!iter->p_end || (p + 1) < iter->p_end) + *qw = ((uint64_t) p[1]) << 32; + *qw |= p[0]; } else - qw = p[0]; + *qw = p[0]; - qw = field_value(qw, field->start, field->end); + *qw = field_value(*qw, field_start, field_end); /* Address & offset types have to be aligned to dwords, their start bit is * a reminder of the alignment requirement. */ - if (field->type.kind == GEN_TYPE_ADDRESS || - field->type.kind == GEN_TYPE_OFFSET) - qw <<= field->start % 32; + if (iter->field->type.kind == GEN_TYPE_ADDRESS || + iter->field->type.kind == GEN_TYPE_OFFSET) + *qw <<= field_start % 32; - return qw; + return true; } -static void +static bool iter_decode_field(struct gen_field_iterator *iter) { union { @@ -881,17 +1049,18 @@ iter_decode_field(struct gen_field_iterator *iter) } v; if (iter->field->name) - strncpy(iter->name, iter->field->name, sizeof(iter->name)); + snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name); else memset(iter->name, 0, sizeof(iter->name)); memset(&v, 0, sizeof(v)); - v.qw = iter_decode_field_raw(iter->field, - &iter->p[iter->bit / 32], iter->p_end); + if (!iter_decode_field_raw(iter, &iter->raw_value)) + return false; const char *enum_name = NULL; + v.qw = iter->raw_value; switch (iter->field->type.kind) { case GEN_TYPE_UNKNOWN: case GEN_TYPE_INT: { @@ -929,10 +1098,14 @@ iter_decode_field(struct gen_field_iterator *iter) snprintf(iter->value, sizeof(iter->value), "%f", (float) v.qw / (1 << iter->field->type.f)); break; - case GEN_TYPE_SFIXED: - /* FIXME: Sign extend extracted field. */ - snprintf(iter->value, sizeof(iter->value), "%s", "foo"); + case GEN_TYPE_SFIXED: { + /* Sign extend before converting */ + int bits = iter->field->type.i + iter->field->type.f + 1; + int64_t v_sign_extend = ((int64_t)(v.qw << (64 - bits))) >> (64 - bits); + snprintf(iter->value, sizeof(iter->value), "%f", + (float) v_sign_extend / (1 << iter->field->type.f)); break; + } case GEN_TYPE_MBO: break; case GEN_TYPE_ENUM: { @@ -944,44 +1117,79 @@ iter_decode_field(struct gen_field_iterator *iter) if (strlen(iter->group->name) == 0) { int length = strlen(iter->name); - snprintf(iter->name + length, sizeof(iter->name) - length, - "[%i]", iter->group_iter); + assert(iter->level >= 0); + + int level = 1; + char *buf = iter->name + length; + while (level <= iter->level) { + int printed = snprintf(buf, sizeof(iter->name) - length, + "[%i]", iter->array_iter[level]); + level++; + length += printed; + buf += printed; + } } if (enum_name) { int length = strlen(iter->value); snprintf(iter->value + length, sizeof(iter->value) - length, " (%s)", enum_name); + } else if (strcmp(iter->name, "Surface Format") == 0 || + strcmp(iter->name, "Source Element Format") == 0) { + if (isl_format_is_valid((enum isl_format)v.qw)) { + const char *fmt_name = isl_format_get_name((enum isl_format)v.qw); + int length = strlen(iter->value); + snprintf(iter->value + length, sizeof(iter->value) - length, + " (%s)", fmt_name); + } } + + return true; } void gen_field_iterator_init(struct gen_field_iterator *iter, struct gen_group *group, - const uint32_t *p, + const uint32_t *p, int p_bit, bool print_colors) { memset(iter, 0, sizeof(*iter)); + iter->groups[iter->level] = group; iter->group = group; - if (group->fields) - iter->field = group->fields; - else - iter->field = group->next->fields; iter->p = p; - iter->p_end = &p[gen_group_get_length(iter->group, iter->p)]; - iter->print_colors = print_colors; + iter->p_bit = p_bit; - iter_decode_field(iter); + int length = gen_group_get_length(iter->group, iter->p); + assert(length >= 0 && "error the length is unknown!"); + iter->p_end = length >= 0 ? &p[length] : NULL; + iter->print_colors = print_colors; } bool gen_field_iterator_next(struct gen_field_iterator *iter) { + /* Initial condition */ + if (!iter->field) { + if (iter->group->fields) + iter_start_field(iter, iter->group->fields); + + bool result = iter_decode_field(iter); + if (!result && iter->p_end) { + /* We're dealing with a non empty struct of length=0 (BLEND_STATE on + * Gen 7.5) + */ + assert(iter->group->dw_length == 0); + } + + return result; + } + if (!iter_advance_field(iter)) return false; - iter_decode_field(iter); + if (!iter_decode_field(iter)) + return false; return true; } @@ -1000,25 +1208,27 @@ gen_field_is_header(struct gen_field *field) { uint32_t bits; - if (field->start >= 32) + /* Instructions are identified by the first DWord. */ + if (field->start >= 32 || + field->end >= 32) return false; - bits = (1U << (field->end - field->start + 1)) - 1; + bits = (1ULL << (field->end - field->start + 1)) - 1; bits <<= field->start; return (field->parent->opcode_mask & bits) != 0; } void -gen_print_group(FILE *outfile, struct gen_group *group, - uint64_t offset, const uint32_t *p, bool color) +gen_print_group(FILE *outfile, struct gen_group *group, uint64_t offset, + const uint32_t *p, int p_bit, bool color) { struct gen_field_iterator iter; int last_dword = -1; - gen_field_iterator_init(&iter, group, p, color); - do { - int iter_dword = iter.bit / 32; + gen_field_iterator_init(&iter, group, p, p_bit, color); + while (gen_field_iterator_next(&iter)) { + int iter_dword = iter.end_bit / 32; if (last_dword != iter_dword) { for (int i = last_dword + 1; i <= iter_dword; i++) print_dword_header(outfile, &iter, offset, i); @@ -1027,10 +1237,11 @@ gen_print_group(FILE *outfile, struct gen_group *group, if (!gen_field_is_header(iter.field)) { fprintf(outfile, " %s: %s\n", iter.name, iter.value); if (iter.struct_desc) { - uint64_t struct_offset = offset + 4 * iter_dword; + int struct_dword = iter.start_bit / 32; + uint64_t struct_offset = offset + 4 * struct_dword; gen_print_group(outfile, iter.struct_desc, struct_offset, - &p[iter_dword], color); + &p[struct_dword], iter.start_bit % 32, color); } } - } while (gen_field_iterator_next(&iter)); + } }