Home | History | Annotate | Download | only in tools
      1 /*
      2  * Copyright  2016 Intel Corporation
      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
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include <stdio.h>
     25 #include <stdbool.h>
     26 #include <stdint.h>
     27 #include <stdarg.h>
     28 #include <string.h>
     29 #include <expat.h>
     30 #include <inttypes.h>
     31 
     32 #include <util/macros.h>
     33 
     34 #include "decoder.h"
     35 
     36 #include "genxml/gen6_xml.h"
     37 #include "genxml/gen7_xml.h"
     38 #include "genxml/gen75_xml.h"
     39 #include "genxml/gen8_xml.h"
     40 #include "genxml/gen9_xml.h"
     41 
     42 #define XML_BUFFER_SIZE 4096
     43 
     44 #define MAKE_GEN(major, minor) ( ((major) << 8) | (minor) )
     45 
     46 struct gen_spec {
     47    uint32_t gen;
     48 
     49    int ncommands;
     50    struct gen_group *commands[256];
     51    int nstructs;
     52    struct gen_group *structs[256];
     53    int nregisters;
     54    struct gen_group *registers[256];
     55    int nenums;
     56    struct gen_enum *enums[256];
     57 };
     58 
     59 struct location {
     60    const char *filename;
     61    int line_number;
     62 };
     63 
     64 struct parser_context {
     65    XML_Parser parser;
     66    int foo;
     67    struct location loc;
     68    const char *platform;
     69 
     70    struct gen_group *group;
     71    struct gen_enum *enoom;
     72 
     73    int nfields;
     74    struct gen_field *fields[128];
     75 
     76    int nvalues;
     77    struct gen_value *values[256];
     78 
     79    struct gen_spec *spec;
     80 };
     81 
     82 const char *
     83 gen_group_get_name(struct gen_group *group)
     84 {
     85    return group->name;
     86 }
     87 
     88 uint32_t
     89 gen_group_get_opcode(struct gen_group *group)
     90 {
     91    return group->opcode;
     92 }
     93 
     94 struct gen_group *
     95 gen_spec_find_struct(struct gen_spec *spec, const char *name)
     96 {
     97    for (int i = 0; i < spec->nstructs; i++)
     98       if (strcmp(spec->structs[i]->name, name) == 0)
     99          return spec->structs[i];
    100 
    101    return NULL;
    102 }
    103 
    104 struct gen_group *
    105 gen_spec_find_register(struct gen_spec *spec, uint32_t offset)
    106 {
    107    for (int i = 0; i < spec->nregisters; i++)
    108       if (spec->registers[i]->register_offset == offset)
    109          return spec->registers[i];
    110 
    111    return NULL;
    112 }
    113 
    114 struct gen_enum *
    115 gen_spec_find_enum(struct gen_spec *spec, const char *name)
    116 {
    117    for (int i = 0; i < spec->nenums; i++)
    118       if (strcmp(spec->enums[i]->name, name) == 0)
    119          return spec->enums[i];
    120 
    121    return NULL;
    122 }
    123 
    124 uint32_t
    125 gen_spec_get_gen(struct gen_spec *spec)
    126 {
    127    return spec->gen;
    128 }
    129 
    130 static void __attribute__((noreturn))
    131 fail(struct location *loc, const char *msg, ...)
    132 {
    133    va_list ap;
    134 
    135    va_start(ap, msg);
    136    fprintf(stderr, "%s:%d: error: ",
    137            loc->filename, loc->line_number);
    138    vfprintf(stderr, msg, ap);
    139    fprintf(stderr, "\n");
    140    va_end(ap);
    141    exit(EXIT_FAILURE);
    142 }
    143 
    144 static void *
    145 fail_on_null(void *p)
    146 {
    147    if (p == NULL) {
    148       fprintf(stderr, "aubinator: out of memory\n");
    149       exit(EXIT_FAILURE);
    150    }
    151 
    152    return p;
    153 }
    154 
    155 static char *
    156 xstrdup(const char *s)
    157 {
    158    return fail_on_null(strdup(s));
    159 }
    160 
    161 static void *
    162 zalloc(size_t s)
    163 {
    164    return calloc(s, 1);
    165 }
    166 
    167 static void *
    168 xzalloc(size_t s)
    169 {
    170    return fail_on_null(zalloc(s));
    171 }
    172 
    173 static struct gen_group *
    174 create_group(struct parser_context *ctx, const char *name, const char **atts)
    175 {
    176    struct gen_group *group;
    177 
    178    group = xzalloc(sizeof(*group));
    179    if (name)
    180       group->name = xstrdup(name);
    181 
    182    group->group_offset = 0;
    183    group->group_count = 0;
    184 
    185    return group;
    186 }
    187 
    188 static struct gen_enum *
    189 create_enum(struct parser_context *ctx, const char *name, const char **atts)
    190 {
    191    struct gen_enum *e;
    192 
    193    e = xzalloc(sizeof(*e));
    194    if (name)
    195       e->name = xstrdup(name);
    196 
    197    e->nvalues = 0;
    198 
    199    return e;
    200 }
    201 
    202 static void
    203 get_group_offset_count(struct parser_context *ctx, const char *name,
    204                        const char **atts, uint32_t *offset, uint32_t *count)
    205 {
    206    char *p;
    207    int i;
    208 
    209    for (i = 0; atts[i]; i += 2) {
    210       if (strcmp(atts[i], "count") == 0)
    211          *count = strtoul(atts[i + 1], &p, 0);
    212       else if (strcmp(atts[i], "start") == 0)
    213          *offset = strtoul(atts[i + 1], &p, 0);
    214    }
    215    return;
    216 }
    217 
    218 static void
    219 get_register_offset(const char **atts, uint32_t *offset)
    220 {
    221    char *p;
    222    int i;
    223 
    224    for (i = 0; atts[i]; i += 2) {
    225       if (strcmp(atts[i], "num") == 0)
    226          *offset = strtoul(atts[i + 1], &p, 0);
    227    }
    228    return;
    229 }
    230 
    231 static void
    232 get_start_end_pos(int *start, int *end)
    233 {
    234    /* start value has to be mod with 32 as we need the relative
    235     * start position in the first DWord. For the end position, add
    236     * the length of the field to the start position to get the
    237     * relative postion in the 64 bit address.
    238     */
    239    if (*end - *start > 32) {
    240       int len = *end - *start;
    241       *start = *start % 32;
    242       *end = *start + len;
    243    } else {
    244       *start = *start % 32;
    245       *end = *end % 32;
    246    }
    247 
    248    return;
    249 }
    250 
    251 static inline uint64_t
    252 mask(int start, int end)
    253 {
    254    uint64_t v;
    255 
    256    v = ~0ULL >> (63 - end + start);
    257 
    258    return v << start;
    259 }
    260 
    261 static inline uint64_t
    262 field(uint64_t value, int start, int end)
    263 {
    264    get_start_end_pos(&start, &end);
    265    return (value & mask(start, end)) >> (start);
    266 }
    267 
    268 static inline uint64_t
    269 field_address(uint64_t value, int start, int end)
    270 {
    271    /* no need to right shift for address/offset */
    272    get_start_end_pos(&start, &end);
    273    return (value & mask(start, end));
    274 }
    275 
    276 static struct gen_type
    277 string_to_type(struct parser_context *ctx, const char *s)
    278 {
    279    int i, f;
    280    struct gen_group *g;
    281    struct gen_enum *e;
    282 
    283    if (strcmp(s, "int") == 0)
    284       return (struct gen_type) { .kind = GEN_TYPE_INT };
    285    else if (strcmp(s, "uint") == 0)
    286       return (struct gen_type) { .kind = GEN_TYPE_UINT };
    287    else if (strcmp(s, "bool") == 0)
    288       return (struct gen_type) { .kind = GEN_TYPE_BOOL };
    289    else if (strcmp(s, "float") == 0)
    290       return (struct gen_type) { .kind = GEN_TYPE_FLOAT };
    291    else if (strcmp(s, "address") == 0)
    292       return (struct gen_type) { .kind = GEN_TYPE_ADDRESS };
    293    else if (strcmp(s, "offset") == 0)
    294       return (struct gen_type) { .kind = GEN_TYPE_OFFSET };
    295    else if (sscanf(s, "u%d.%d", &i, &f) == 2)
    296       return (struct gen_type) { .kind = GEN_TYPE_UFIXED, .i = i, .f = f };
    297    else if (sscanf(s, "s%d.%d", &i, &f) == 2)
    298       return (struct gen_type) { .kind = GEN_TYPE_SFIXED, .i = i, .f = f };
    299    else if (g = gen_spec_find_struct(ctx->spec, s), g != NULL)
    300       return (struct gen_type) { .kind = GEN_TYPE_STRUCT, .gen_struct = g };
    301    else if (e = gen_spec_find_enum(ctx->spec, s), e != NULL)
    302       return (struct gen_type) { .kind = GEN_TYPE_ENUM, .gen_enum = e };
    303    else if (strcmp(s, "mbo") == 0)
    304       return (struct gen_type) { .kind = GEN_TYPE_MBO };
    305    else
    306       fail(&ctx->loc, "invalid type: %s", s);
    307 }
    308 
    309 static struct gen_field *
    310 create_field(struct parser_context *ctx, const char **atts)
    311 {
    312    struct gen_field *field;
    313    char *p;
    314    int i;
    315 
    316    field = xzalloc(sizeof(*field));
    317 
    318    for (i = 0; atts[i]; i += 2) {
    319       if (strcmp(atts[i], "name") == 0)
    320          field->name = xstrdup(atts[i + 1]);
    321       else if (strcmp(atts[i], "start") == 0)
    322          field->start = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0);
    323       else if (strcmp(atts[i], "end") == 0) {
    324          field->end = ctx->group->group_offset+strtoul(atts[i + 1], &p, 0);
    325          if (ctx->group->group_offset)
    326             ctx->group->group_offset = field->end+1;
    327       } else if (strcmp(atts[i], "type") == 0)
    328          field->type = string_to_type(ctx, atts[i + 1]);
    329       else if (strcmp(atts[i], "default") == 0 &&
    330                field->start >= 16 && field->end <= 31) {
    331          field->has_default = true;
    332          field->default_value = strtoul(atts[i + 1], &p, 0);
    333       }
    334    }
    335 
    336    return field;
    337 }
    338 
    339 static struct gen_value *
    340 create_value(struct parser_context *ctx, const char **atts)
    341 {
    342    struct gen_value *value = xzalloc(sizeof(*value));
    343 
    344    for (int i = 0; atts[i]; i += 2) {
    345       if (strcmp(atts[i], "name") == 0)
    346          value->name = xstrdup(atts[i + 1]);
    347       else if (strcmp(atts[i], "value") == 0)
    348          value->value = strtoul(atts[i + 1], NULL, 0);
    349    }
    350 
    351    return value;
    352 }
    353 
    354 static void
    355 start_element(void *data, const char *element_name, const char **atts)
    356 {
    357    struct parser_context *ctx = data;
    358    int i;
    359    const char *name = NULL;
    360    const char *gen = NULL;
    361 
    362    ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
    363 
    364    for (i = 0; atts[i]; i += 2) {
    365       if (strcmp(atts[i], "name") == 0)
    366          name = atts[i + 1];
    367       else if (strcmp(atts[i], "gen") == 0)
    368          gen = atts[i + 1];
    369    }
    370 
    371    if (strcmp(element_name, "genxml") == 0) {
    372       if (name == NULL)
    373          fail(&ctx->loc, "no platform name given");
    374       if (gen == NULL)
    375          fail(&ctx->loc, "no gen given");
    376 
    377       ctx->platform = xstrdup(name);
    378       int major, minor;
    379       int n = sscanf(gen, "%d.%d", &major, &minor);
    380       if (n == 0)
    381          fail(&ctx->loc, "invalid gen given: %s", gen);
    382       if (n == 1)
    383          minor = 0;
    384 
    385       ctx->spec->gen = MAKE_GEN(major, minor);
    386    } else if (strcmp(element_name, "instruction") == 0 ||
    387               strcmp(element_name, "struct") == 0) {
    388       ctx->group = create_group(ctx, name, atts);
    389    } else if (strcmp(element_name, "register") == 0) {
    390       ctx->group = create_group(ctx, name, atts);
    391       get_register_offset(atts, &ctx->group->register_offset);
    392    } else if (strcmp(element_name, "group") == 0) {
    393       get_group_offset_count(ctx, name, atts, &ctx->group->group_offset,
    394                              &ctx->group->group_count);
    395    } else if (strcmp(element_name, "field") == 0) {
    396       do {
    397          ctx->fields[ctx->nfields++] = create_field(ctx, atts);
    398          if (ctx->group->group_count)
    399             ctx->group->group_count--;
    400       } while (ctx->group->group_count > 0);
    401    } else if (strcmp(element_name, "enum") == 0) {
    402       ctx->enoom = create_enum(ctx, name, atts);
    403    } else if (strcmp(element_name, "value") == 0) {
    404       ctx->values[ctx->nvalues++] = create_value(ctx, atts);
    405    }
    406 }
    407 
    408 static void
    409 end_element(void *data, const char *name)
    410 {
    411    struct parser_context *ctx = data;
    412    struct gen_spec *spec = ctx->spec;
    413 
    414    if (strcmp(name, "instruction") == 0 ||
    415       strcmp(name, "struct") == 0 ||
    416       strcmp(name, "register") == 0) {
    417       size_t size = ctx->nfields * sizeof(ctx->fields[0]);
    418       struct gen_group *group = ctx->group;
    419 
    420       group->fields = xzalloc(size);
    421       group->nfields = ctx->nfields;
    422       memcpy(group->fields, ctx->fields, size);
    423       ctx->nfields = 0;
    424       ctx->group = NULL;
    425 
    426       for (int i = 0; i < group->nfields; i++) {
    427          if (group->fields[i]->start >= 16 &&
    428             group->fields[i]->end <= 31 &&
    429             group->fields[i]->has_default) {
    430             group->opcode_mask |=
    431                mask(group->fields[i]->start % 32, group->fields[i]->end % 32);
    432             group->opcode |=
    433                group->fields[i]->default_value << group->fields[i]->start;
    434          }
    435       }
    436 
    437       if (strcmp(name, "instruction") == 0)
    438          spec->commands[spec->ncommands++] = group;
    439       else if (strcmp(name, "struct") == 0)
    440          spec->structs[spec->nstructs++] = group;
    441       else if (strcmp(name, "register") == 0)
    442          spec->registers[spec->nregisters++] = group;
    443    } else if (strcmp(name, "group") == 0) {
    444       ctx->group->group_offset = 0;
    445       ctx->group->group_count = 0;
    446    } else if (strcmp(name, "field") == 0) {
    447       assert(ctx->nfields > 0);
    448       struct gen_field *field = ctx->fields[ctx->nfields - 1];
    449       size_t size = ctx->nvalues * sizeof(ctx->values[0]);
    450       field->inline_enum.values = xzalloc(size);
    451       field->inline_enum.nvalues = ctx->nvalues;
    452       memcpy(field->inline_enum.values, ctx->values, size);
    453       ctx->nvalues = 0;
    454    } else if (strcmp(name, "enum") == 0) {
    455       struct gen_enum *e = ctx->enoom;
    456       size_t size = ctx->nvalues * sizeof(ctx->values[0]);
    457       e->values = xzalloc(size);
    458       e->nvalues = ctx->nvalues;
    459       memcpy(e->values, ctx->values, size);
    460       ctx->nvalues = 0;
    461       ctx->enoom = NULL;
    462       spec->enums[spec->nenums++] = e;
    463    }
    464 }
    465 
    466 static void
    467 character_data(void *data, const XML_Char *s, int len)
    468 {
    469 }
    470 
    471 static int
    472 devinfo_to_gen(const struct gen_device_info *devinfo)
    473 {
    474    int value = 10 * devinfo->gen;
    475 
    476    if (devinfo->is_baytrail || devinfo->is_haswell)
    477       value += 5;
    478 
    479    return value;
    480 }
    481 
    482 static const struct {
    483    int gen;
    484    const uint8_t *data;
    485    size_t data_length;
    486 } gen_data[] = {
    487    { .gen = 60, .data = gen6_xml, .data_length = sizeof(gen6_xml) },
    488    { .gen = 70, .data = gen7_xml, .data_length = sizeof(gen7_xml) },
    489    { .gen = 75, .data = gen75_xml, .data_length = sizeof(gen75_xml) },
    490    { .gen = 80, .data = gen8_xml, .data_length = sizeof(gen8_xml) },
    491    { .gen = 90, .data = gen9_xml, .data_length = sizeof(gen9_xml) }
    492 };
    493 
    494 static const uint8_t *
    495 devinfo_to_xml_data(const struct gen_device_info *devinfo,
    496                     uint32_t *data_length)
    497 {
    498    int i, gen = devinfo_to_gen(devinfo);
    499 
    500    for (i = 0; i < ARRAY_SIZE(gen_data); i++) {
    501       if (gen_data[i].gen == gen) {
    502          *data_length = gen_data[i].data_length;
    503          return gen_data[i].data;
    504       }
    505    }
    506 
    507    unreachable("Unknown generation");
    508    return NULL;
    509 }
    510 
    511 struct gen_spec *
    512 gen_spec_load(const struct gen_device_info *devinfo)
    513 {
    514    struct parser_context ctx;
    515    void *buf;
    516    const void *data;
    517    uint32_t data_length = 0;
    518 
    519    memset(&ctx, 0, sizeof ctx);
    520    ctx.parser = XML_ParserCreate(NULL);
    521    XML_SetUserData(ctx.parser, &ctx);
    522    if (ctx.parser == NULL) {
    523       fprintf(stderr, "failed to create parser\n");
    524       return NULL;
    525    }
    526 
    527    XML_SetElementHandler(ctx.parser, start_element, end_element);
    528    XML_SetCharacterDataHandler(ctx.parser, character_data);
    529 
    530    ctx.spec = xzalloc(sizeof(*ctx.spec));
    531 
    532    data = devinfo_to_xml_data(devinfo, &data_length);
    533    buf = XML_GetBuffer(ctx.parser, data_length);
    534 
    535    memcpy(buf, data, data_length);
    536 
    537    if (XML_ParseBuffer(ctx.parser, data_length, true) == 0) {
    538       fprintf(stderr,
    539               "Error parsing XML at line %ld col %ld: %s\n",
    540               XML_GetCurrentLineNumber(ctx.parser),
    541               XML_GetCurrentColumnNumber(ctx.parser),
    542               XML_ErrorString(XML_GetErrorCode(ctx.parser)));
    543       XML_ParserFree(ctx.parser);
    544       return NULL;
    545    }
    546 
    547    XML_ParserFree(ctx.parser);
    548 
    549    return ctx.spec;
    550 }
    551 
    552 struct gen_spec *
    553 gen_spec_load_from_path(const struct gen_device_info *devinfo,
    554                         const char *path)
    555 {
    556    struct parser_context ctx;
    557    size_t len, filename_len = strlen(path) + 20;
    558    char *filename = malloc(filename_len);
    559    void *buf;
    560    FILE *input;
    561 
    562    len = snprintf(filename, filename_len, "%s/gen%i.xml",
    563                   path, devinfo_to_gen(devinfo));
    564    assert(len < filename_len);
    565 
    566    input = fopen(filename, "r");
    567    if (input == NULL) {
    568       fprintf(stderr, "failed to open xml description\n");
    569       free(filename);
    570       return NULL;
    571    }
    572 
    573    memset(&ctx, 0, sizeof ctx);
    574    ctx.parser = XML_ParserCreate(NULL);
    575    XML_SetUserData(ctx.parser, &ctx);
    576    if (ctx.parser == NULL) {
    577       fprintf(stderr, "failed to create parser\n");
    578       fclose(input);
    579       free(filename);
    580       return NULL;
    581    }
    582 
    583    XML_SetElementHandler(ctx.parser, start_element, end_element);
    584    XML_SetCharacterDataHandler(ctx.parser, character_data);
    585    ctx.loc.filename = filename;
    586    ctx.spec = xzalloc(sizeof(*ctx.spec));
    587 
    588    do {
    589       buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
    590       len = fread(buf, 1, XML_BUFFER_SIZE, input);
    591       if (len < 0) {
    592          fprintf(stderr, "fread: %m\n");
    593          fclose(input);
    594          free(filename);
    595          return NULL;
    596       }
    597       if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
    598          fprintf(stderr,
    599                  "Error parsing XML at line %ld col %ld: %s\n",
    600                  XML_GetCurrentLineNumber(ctx.parser),
    601                  XML_GetCurrentColumnNumber(ctx.parser),
    602                  XML_ErrorString(XML_GetErrorCode(ctx.parser)));
    603          fclose(input);
    604          free(filename);
    605          return NULL;
    606       }
    607    } while (len > 0);
    608 
    609    XML_ParserFree(ctx.parser);
    610 
    611    fclose(input);
    612    free(filename);
    613 
    614    return ctx.spec;
    615 }
    616 
    617 struct gen_group *
    618 gen_spec_find_instruction(struct gen_spec *spec, const uint32_t *p)
    619 {
    620    for (int i = 0; i < spec->ncommands; i++) {
    621       uint32_t opcode = *p & spec->commands[i]->opcode_mask;
    622       if (opcode == spec->commands[i]->opcode)
    623          return spec->commands[i];
    624    }
    625 
    626    return NULL;
    627 }
    628 
    629 int
    630 gen_group_get_length(struct gen_group *group, const uint32_t *p)
    631 {
    632    uint32_t h = p[0];
    633    uint32_t type = field(h, 29, 31);
    634 
    635    switch (type) {
    636    case 0: /* MI */ {
    637       uint32_t opcode = field(h, 23, 28);
    638       if (opcode < 16)
    639          return 1;
    640       else
    641          return field(h, 0, 7) + 2;
    642       break;
    643    }
    644 
    645    case 3: /* Render */ {
    646       uint32_t subtype = field(h, 27, 28);
    647       switch (subtype) {
    648       case 0:
    649          return field(h, 0, 7) + 2;
    650       case 1:
    651          return 1;
    652       case 2:
    653          return 2;
    654       case 3:
    655          return field(h, 0, 7) + 2;
    656       }
    657    }
    658    }
    659 
    660    unreachable("bad opcode");
    661 }
    662 
    663 void
    664 gen_field_iterator_init(struct gen_field_iterator *iter,
    665                         struct gen_group *group,
    666                         const uint32_t *p,
    667                         bool print_colors)
    668 {
    669    iter->group = group;
    670    iter->p = p;
    671    iter->i = 0;
    672    iter->print_colors = print_colors;
    673 }
    674 
    675 static void
    676 gen_enum_write_value(char *str, size_t max_length,
    677                       struct gen_enum *e, uint64_t value)
    678 {
    679    for (int i = 0; i < e->nvalues; i++) {
    680       if (e->values[i]->value == value) {
    681          strncpy(str, e->values[i]->name, max_length);
    682          return;
    683       }
    684    }
    685 }
    686 
    687 bool
    688 gen_field_iterator_next(struct gen_field_iterator *iter)
    689 {
    690    struct gen_field *f;
    691    union {
    692       uint64_t qw;
    693       float f;
    694    } v;
    695 
    696    if (iter->i == iter->group->nfields)
    697       return false;
    698 
    699    f = iter->group->fields[iter->i++];
    700    iter->name = f->name;
    701    int index = f->start / 32;
    702 
    703    if ((f->end - f->start) > 32)
    704       v.qw = ((uint64_t) iter->p[index+1] << 32) | iter->p[index];
    705    else
    706       v.qw = iter->p[index];
    707 
    708    iter->description[0] = '\0';
    709 
    710    switch (f->type.kind) {
    711    case GEN_TYPE_UNKNOWN:
    712    case GEN_TYPE_INT: {
    713       uint64_t value = field(v.qw, f->start, f->end);
    714       snprintf(iter->value, sizeof(iter->value),
    715                "%"PRId64, value);
    716       gen_enum_write_value(iter->description, sizeof(iter->description),
    717                            &f->inline_enum, value);
    718       break;
    719    }
    720    case GEN_TYPE_UINT: {
    721       uint64_t value = field(v.qw, f->start, f->end);
    722       snprintf(iter->value, sizeof(iter->value),
    723                "%"PRIu64, value);
    724       gen_enum_write_value(iter->description, sizeof(iter->description),
    725                             &f->inline_enum, value);
    726       break;
    727    }
    728    case GEN_TYPE_BOOL: {
    729       const char *true_string =
    730          iter->print_colors ? "\e[0;35mtrue\e[0m" : "true";
    731       snprintf(iter->value, sizeof(iter->value),
    732                "%s", field(v.qw, f->start, f->end) ? true_string : "false");
    733       break;
    734    }
    735    case GEN_TYPE_FLOAT:
    736       snprintf(iter->value, sizeof(iter->value), "%f", v.f);
    737       break;
    738    case GEN_TYPE_ADDRESS:
    739    case GEN_TYPE_OFFSET:
    740       snprintf(iter->value, sizeof(iter->value),
    741                "0x%08"PRIx64, field_address(v.qw, f->start, f->end));
    742       break;
    743    case GEN_TYPE_STRUCT:
    744       snprintf(iter->value, sizeof(iter->value),
    745                "<struct %s %d>", f->type.gen_struct->name, (f->start / 32));
    746       break;
    747    case GEN_TYPE_UFIXED:
    748       snprintf(iter->value, sizeof(iter->value),
    749                "%f", (float) field(v.qw, f->start, f->end) / (1 << f->type.f));
    750       break;
    751    case GEN_TYPE_SFIXED:
    752       /* FIXME: Sign extend extracted field. */
    753       snprintf(iter->value, sizeof(iter->value), "%s", "foo");
    754       break;
    755    case GEN_TYPE_MBO:
    756        break;
    757    case GEN_TYPE_ENUM: {
    758       uint64_t value = field(v.qw, f->start, f->end);
    759       snprintf(iter->value, sizeof(iter->value),
    760                "%"PRId64, value);
    761       gen_enum_write_value(iter->description, sizeof(iter->description),
    762                            f->type.gen_enum, value);
    763       break;
    764    }
    765    }
    766 
    767    return true;
    768 }
    769