Home | History | Annotate | Line # | Download | only in common
      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 #include <zlib.h>
     32 
     33 #include <util/macros.h>
     34 #include <util/ralloc.h>
     35 
     36 #include "gen_decoder.h"
     37 
     38 #include "isl/isl.h"
     39 #include "genxml/genX_xml.h"
     40 
     41 #define XML_BUFFER_SIZE 4096
     42 #define MAX_VALUE_ITEMS 128
     43 
     44 struct location {
     45    const char *filename;
     46    int line_number;
     47 };
     48 
     49 struct parser_context {
     50    XML_Parser parser;
     51    int foo;
     52    struct location loc;
     53 
     54    struct gen_group *group;
     55    struct gen_enum *enoom;
     56 
     57    int n_values, n_allocated_values;
     58    struct gen_value **values;
     59 
     60    struct gen_field *last_field;
     61 
     62    struct gen_spec *spec;
     63 };
     64 
     65 const char *
     66 gen_group_get_name(struct gen_group *group)
     67 {
     68    return group->name;
     69 }
     70 
     71 uint32_t
     72 gen_group_get_opcode(struct gen_group *group)
     73 {
     74    return group->opcode;
     75 }
     76 
     77 struct gen_group *
     78 gen_spec_find_struct(struct gen_spec *spec, const char *name)
     79 {
     80    struct hash_entry *entry = _mesa_hash_table_search(spec->structs,
     81                                                       name);
     82    return entry ? entry->data : NULL;
     83 }
     84 
     85 struct gen_group *
     86 gen_spec_find_register(struct gen_spec *spec, uint32_t offset)
     87 {
     88    struct hash_entry *entry =
     89       _mesa_hash_table_search(spec->registers_by_offset,
     90                               (void *) (uintptr_t) offset);
     91    return entry ? entry->data : NULL;
     92 }
     93 
     94 struct gen_group *
     95 gen_spec_find_register_by_name(struct gen_spec *spec, const char *name)
     96 {
     97    struct hash_entry *entry =
     98       _mesa_hash_table_search(spec->registers_by_name, name);
     99    return entry ? entry->data : NULL;
    100 }
    101 
    102 struct gen_enum *
    103 gen_spec_find_enum(struct gen_spec *spec, const char *name)
    104 {
    105    struct hash_entry *entry = _mesa_hash_table_search(spec->enums,
    106                                                       name);
    107    return entry ? entry->data : NULL;
    108 }
    109 
    110 uint32_t
    111 gen_spec_get_gen(struct gen_spec *spec)
    112 {
    113    return spec->gen;
    114 }
    115 
    116 static void __attribute__((noreturn))
    117 fail(struct location *loc, const char *msg, ...)
    118 {
    119    va_list ap;
    120 
    121    va_start(ap, msg);
    122    fprintf(stderr, "%s:%d: error: ",
    123            loc->filename, loc->line_number);
    124    vfprintf(stderr, msg, ap);
    125    fprintf(stderr, "\n");
    126    va_end(ap);
    127    exit(EXIT_FAILURE);
    128 }
    129 
    130 static void
    131 get_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count,
    132                        uint32_t *size, bool *variable)
    133 {
    134    for (int i = 0; atts[i]; i += 2) {
    135       char *p;
    136 
    137       if (strcmp(atts[i], "count") == 0) {
    138          *count = strtoul(atts[i + 1], &p, 0);
    139          if (*count == 0)
    140             *variable = true;
    141       } else if (strcmp(atts[i], "start") == 0) {
    142          *offset = strtoul(atts[i + 1], &p, 0);
    143       } else if (strcmp(atts[i], "size") == 0) {
    144          *size = strtoul(atts[i + 1], &p, 0);
    145       }
    146    }
    147    return;
    148 }
    149 
    150 static struct gen_group *
    151 create_group(struct parser_context *ctx,
    152              const char *name,
    153              const char **atts,
    154              struct gen_group *parent,
    155              bool fixed_length)
    156 {
    157    struct gen_group *group;
    158 
    159    group = rzalloc(ctx->spec, struct gen_group);
    160    if (name)
    161       group->name = ralloc_strdup(group, name);
    162 
    163    group->spec = ctx->spec;
    164    group->variable = false;
    165    group->fixed_length = fixed_length;
    166    group->dword_length_field = NULL;
    167    group->dw_length = 0;
    168    group->engine_mask = I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER) |
    169                         I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO) |
    170                         I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY);
    171    group->bias = 1;
    172 
    173    for (int i = 0; atts[i]; i += 2) {
    174       char *p;
    175       if (strcmp(atts[i], "length") == 0) {
    176          group->dw_length = strtoul(atts[i + 1], &p, 0);
    177       } else if (strcmp(atts[i], "bias") == 0) {
    178          group->bias = strtoul(atts[i + 1], &p, 0);
    179       } else if (strcmp(atts[i], "engine") == 0) {
    180          void *mem_ctx = ralloc_context(NULL);
    181          char *tmp = ralloc_strdup(mem_ctx, atts[i + 1]);
    182          char *save_ptr;
    183          char *tok = strtok_r(tmp, "|", &save_ptr);
    184 
    185          group->engine_mask = 0;
    186          while (tok != NULL) {
    187             if (strcmp(tok, "render") == 0) {
    188                group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER);
    189             } else if (strcmp(tok, "video") == 0) {
    190                group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO);
    191             } else if (strcmp(tok, "blitter") == 0) {
    192                group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY);
    193             } else {
    194                fprintf(stderr, "unknown engine class defined for instruction \"%s\": %s\n", name, atts[i + 1]);
    195             }
    196 
    197             tok = strtok_r(NULL, "|", &save_ptr);
    198          }
    199 
    200          ralloc_free(mem_ctx);
    201       }
    202    }
    203 
    204    if (parent) {
    205       group->parent = parent;
    206       get_group_offset_count(atts,
    207                              &group->group_offset,
    208                              &group->group_count,
    209                              &group->group_size,
    210                              &group->variable);
    211    }
    212 
    213    return group;
    214 }
    215 
    216 static struct gen_enum *
    217 create_enum(struct parser_context *ctx, const char *name, const char **atts)
    218 {
    219    struct gen_enum *e;
    220 
    221    e = rzalloc(ctx->spec, struct gen_enum);
    222    if (name)
    223       e->name = ralloc_strdup(e, name);
    224 
    225    return e;
    226 }
    227 
    228 static void
    229 get_register_offset(const char **atts, uint32_t *offset)
    230 {
    231    for (int i = 0; atts[i]; i += 2) {
    232       char *p;
    233 
    234       if (strcmp(atts[i], "num") == 0)
    235          *offset = strtoul(atts[i + 1], &p, 0);
    236    }
    237    return;
    238 }
    239 
    240 static void
    241 get_start_end_pos(int *start, int *end)
    242 {
    243    /* start value has to be mod with 32 as we need the relative
    244     * start position in the first DWord. For the end position, add
    245     * the length of the field to the start position to get the
    246     * relative postion in the 64 bit address.
    247     */
    248    if (*end - *start > 32) {
    249       int len = *end - *start;
    250       *start = *start % 32;
    251       *end = *start + len;
    252    } else {
    253       *start = *start % 32;
    254       *end = *end % 32;
    255    }
    256 
    257    return;
    258 }
    259 
    260 static inline uint64_t
    261 mask(int start, int end)
    262 {
    263    uint64_t v;
    264 
    265    v = ~0ULL >> (63 - end + start);
    266 
    267    return v << start;
    268 }
    269 
    270 static inline uint64_t
    271 field_value(uint64_t value, int start, int end)
    272 {
    273    get_start_end_pos(&start, &end);
    274    return (value & mask(start, end)) >> (start);
    275 }
    276 
    277 static struct gen_type
    278 string_to_type(struct parser_context *ctx, const char *s)
    279 {
    280    int i, f;
    281    struct gen_group *g;
    282    struct gen_enum *e;
    283 
    284    if (strcmp(s, "int") == 0)
    285       return (struct gen_type) { .kind = GEN_TYPE_INT };
    286    else if (strcmp(s, "uint") == 0)
    287       return (struct gen_type) { .kind = GEN_TYPE_UINT };
    288    else if (strcmp(s, "bool") == 0)
    289       return (struct gen_type) { .kind = GEN_TYPE_BOOL };
    290    else if (strcmp(s, "float") == 0)
    291       return (struct gen_type) { .kind = GEN_TYPE_FLOAT };
    292    else if (strcmp(s, "address") == 0)
    293       return (struct gen_type) { .kind = GEN_TYPE_ADDRESS };
    294    else if (strcmp(s, "offset") == 0)
    295       return (struct gen_type) { .kind = GEN_TYPE_OFFSET };
    296    else if (sscanf(s, "u%d.%d", &i, &f) == 2)
    297       return (struct gen_type) { .kind = GEN_TYPE_UFIXED, .i = i, .f = f };
    298    else if (sscanf(s, "s%d.%d", &i, &f) == 2)
    299       return (struct gen_type) { .kind = GEN_TYPE_SFIXED, .i = i, .f = f };
    300    else if (g = gen_spec_find_struct(ctx->spec, s), g != NULL)
    301       return (struct gen_type) { .kind = GEN_TYPE_STRUCT, .gen_struct = g };
    302    else if (e = gen_spec_find_enum(ctx->spec, s), e != NULL)
    303       return (struct gen_type) { .kind = GEN_TYPE_ENUM, .gen_enum = e };
    304    else if (strcmp(s, "mbo") == 0)
    305       return (struct gen_type) { .kind = GEN_TYPE_MBO };
    306    else
    307       fail(&ctx->loc, "invalid type: %s", s);
    308 }
    309 
    310 static struct gen_field *
    311 create_field(struct parser_context *ctx, const char **atts)
    312 {
    313    struct gen_field *field;
    314 
    315    field = rzalloc(ctx->group, struct gen_field);
    316    field->parent = ctx->group;
    317 
    318    for (int i = 0; atts[i]; i += 2) {
    319       char *p;
    320 
    321       if (strcmp(atts[i], "name") == 0) {
    322          field->name = ralloc_strdup(field, atts[i + 1]);
    323          if (strcmp(field->name, "DWord Length") == 0) {
    324             field->parent->dword_length_field = field;
    325          }
    326       } else if (strcmp(atts[i], "start") == 0) {
    327          field->start = strtoul(atts[i + 1], &p, 0);
    328       } else if (strcmp(atts[i], "end") == 0) {
    329          field->end = strtoul(atts[i + 1], &p, 0);
    330       } else if (strcmp(atts[i], "type") == 0) {
    331          field->type = string_to_type(ctx, atts[i + 1]);
    332       } else if (strcmp(atts[i], "default") == 0 &&
    333                field->start >= 16 && field->end <= 31) {
    334          field->has_default = true;
    335          field->default_value = strtoul(atts[i + 1], &p, 0);
    336       }
    337    }
    338 
    339    return field;
    340 }
    341 
    342 static struct gen_value *
    343 create_value(struct parser_context *ctx, const char **atts)
    344 {
    345    struct gen_value *value = rzalloc(ctx->values, struct gen_value);
    346 
    347    for (int i = 0; atts[i]; i += 2) {
    348       if (strcmp(atts[i], "name") == 0)
    349          value->name = ralloc_strdup(value, atts[i + 1]);
    350       else if (strcmp(atts[i], "value") == 0)
    351          value->value = strtoul(atts[i + 1], NULL, 0);
    352    }
    353 
    354    return value;
    355 }
    356 
    357 static struct gen_field *
    358 create_and_append_field(struct parser_context *ctx,
    359                         const char **atts)
    360 {
    361    struct gen_field *field = create_field(ctx, atts);
    362    struct gen_field *prev = NULL, *list = ctx->group->fields;
    363 
    364    while (list && field->start > list->start) {
    365       prev = list;
    366       list = list->next;
    367    }
    368 
    369    field->next = list;
    370    if (prev == NULL)
    371       ctx->group->fields = field;
    372    else
    373       prev->next = field;
    374 
    375    return field;
    376 }
    377 
    378 static void
    379 start_element(void *data, const char *element_name, const char **atts)
    380 {
    381    struct parser_context *ctx = data;
    382    const char *name = NULL;
    383    const char *gen = NULL;
    384 
    385    ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
    386 
    387    for (int i = 0; atts[i]; i += 2) {
    388       if (strcmp(atts[i], "name") == 0)
    389          name = atts[i + 1];
    390       else if (strcmp(atts[i], "gen") == 0)
    391          gen = atts[i + 1];
    392    }
    393 
    394    if (strcmp(element_name, "genxml") == 0) {
    395       if (name == NULL)
    396          fail(&ctx->loc, "no platform name given");
    397       if (gen == NULL)
    398          fail(&ctx->loc, "no gen given");
    399 
    400       int major, minor;
    401       int n = sscanf(gen, "%d.%d", &major, &minor);
    402       if (n == 0)
    403          fail(&ctx->loc, "invalid gen given: %s", gen);
    404       if (n == 1)
    405          minor = 0;
    406 
    407       ctx->spec->gen = gen_make_gen(major, minor);
    408    } else if (strcmp(element_name, "instruction") == 0) {
    409       ctx->group = create_group(ctx, name, atts, NULL, false);
    410    } else if (strcmp(element_name, "struct") == 0) {
    411       ctx->group = create_group(ctx, name, atts, NULL, true);
    412    } else if (strcmp(element_name, "register") == 0) {
    413       ctx->group = create_group(ctx, name, atts, NULL, true);
    414       get_register_offset(atts, &ctx->group->register_offset);
    415    } else if (strcmp(element_name, "group") == 0) {
    416       struct gen_group *previous_group = ctx->group;
    417       while (previous_group->next)
    418          previous_group = previous_group->next;
    419 
    420       struct gen_group *group = create_group(ctx, "", atts, ctx->group, false);
    421       previous_group->next = group;
    422       ctx->group = group;
    423    } else if (strcmp(element_name, "field") == 0) {
    424       ctx->last_field = create_and_append_field(ctx, atts);
    425    } else if (strcmp(element_name, "enum") == 0) {
    426       ctx->enoom = create_enum(ctx, name, atts);
    427    } else if (strcmp(element_name, "value") == 0) {
    428       if (ctx->n_values >= ctx->n_allocated_values) {
    429          ctx->n_allocated_values = MAX2(2, ctx->n_allocated_values * 2);
    430          ctx->values = reralloc_array_size(ctx->spec, ctx->values,
    431                                            sizeof(struct gen_value *),
    432                                            ctx->n_allocated_values);
    433       }
    434       assert(ctx->n_values < ctx->n_allocated_values);
    435       ctx->values[ctx->n_values++] = create_value(ctx, atts);
    436    }
    437 
    438 }
    439 
    440 static void
    441 end_element(void *data, const char *name)
    442 {
    443    struct parser_context *ctx = data;
    444    struct gen_spec *spec = ctx->spec;
    445 
    446    if (strcmp(name, "instruction") == 0 ||
    447        strcmp(name, "struct") == 0 ||
    448        strcmp(name, "register") == 0) {
    449       struct gen_group *group = ctx->group;
    450       struct gen_field *list = group->fields;
    451 
    452       ctx->group = ctx->group->parent;
    453 
    454       while (list && list->end <= 31) {
    455          if (list->start >= 16 && list->has_default) {
    456             group->opcode_mask |=
    457                mask(list->start % 32, list->end % 32);
    458             group->opcode |= list->default_value << list->start;
    459          }
    460          list = list->next;
    461       }
    462 
    463       if (strcmp(name, "instruction") == 0)
    464          _mesa_hash_table_insert(spec->commands, group->name, group);
    465       else if (strcmp(name, "struct") == 0)
    466          _mesa_hash_table_insert(spec->structs, group->name, group);
    467       else if (strcmp(name, "register") == 0) {
    468          _mesa_hash_table_insert(spec->registers_by_name, group->name, group);
    469          _mesa_hash_table_insert(spec->registers_by_offset,
    470                                  (void *) (uintptr_t) group->register_offset,
    471                                  group);
    472       }
    473    } else if (strcmp(name, "group") == 0) {
    474       ctx->group = ctx->group->parent;
    475    } else if (strcmp(name, "field") == 0) {
    476       struct gen_field *field = ctx->last_field;
    477       ctx->last_field = NULL;
    478       field->inline_enum.values = ctx->values;
    479       field->inline_enum.nvalues = ctx->n_values;
    480       ctx->values = ralloc_array(ctx->spec, struct gen_value*, ctx->n_allocated_values = 2);
    481       ctx->n_values = 0;
    482    } else if (strcmp(name, "enum") == 0) {
    483       struct gen_enum *e = ctx->enoom;
    484       e->values = ctx->values;
    485       e->nvalues = ctx->n_values;
    486       ctx->values = ralloc_array(ctx->spec, struct gen_value*, ctx->n_allocated_values = 2);
    487       ctx->n_values = 0;
    488       ctx->enoom = NULL;
    489       _mesa_hash_table_insert(spec->enums, e->name, e);
    490    }
    491 }
    492 
    493 static void
    494 character_data(void *data, const XML_Char *s, int len)
    495 {
    496 }
    497 
    498 static int
    499 devinfo_to_gen(const struct gen_device_info *devinfo, bool x10)
    500 {
    501    if (devinfo->is_baytrail || devinfo->is_haswell) {
    502       return devinfo->gen * 10 + 5;
    503    }
    504 
    505    return x10 ? devinfo->gen * 10 : devinfo->gen;
    506 }
    507 
    508 static uint32_t zlib_inflate(const void *compressed_data,
    509                              uint32_t compressed_len,
    510                              void **out_ptr)
    511 {
    512    struct z_stream_s zstream;
    513    void *out;
    514 
    515    memset(&zstream, 0, sizeof(zstream));
    516 
    517    zstream.next_in = (unsigned char *)compressed_data;
    518    zstream.avail_in = compressed_len;
    519 
    520    if (inflateInit(&zstream) != Z_OK)
    521       return 0;
    522 
    523    out = malloc(4096);
    524    zstream.next_out = out;
    525    zstream.avail_out = 4096;
    526 
    527    do {
    528       switch (inflate(&zstream, Z_SYNC_FLUSH)) {
    529       case Z_STREAM_END:
    530          goto end;
    531       case Z_OK:
    532          break;
    533       default:
    534          inflateEnd(&zstream);
    535          return 0;
    536       }
    537 
    538       if (zstream.avail_out)
    539          break;
    540 
    541       out = realloc(out, 2*zstream.total_out);
    542       if (out == NULL) {
    543          inflateEnd(&zstream);
    544          return 0;
    545       }
    546 
    547       zstream.next_out = (unsigned char *)out + zstream.total_out;
    548       zstream.avail_out = zstream.total_out;
    549    } while (1);
    550  end:
    551    inflateEnd(&zstream);
    552    *out_ptr = out;
    553    return zstream.total_out;
    554 }
    555 
    556 static uint32_t _hash_uint32(const void *key)
    557 {
    558    return (uint32_t) (uintptr_t) key;
    559 }
    560 
    561 static struct gen_spec *
    562 gen_spec_init(void)
    563 {
    564    struct gen_spec *spec;
    565    spec = rzalloc(NULL, struct gen_spec);
    566    if (spec == NULL)
    567       return NULL;
    568 
    569    spec->commands =
    570       _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
    571    spec->structs =
    572       _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
    573    spec->registers_by_name =
    574       _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
    575    spec->registers_by_offset =
    576       _mesa_hash_table_create(spec, _hash_uint32, _mesa_key_pointer_equal);
    577    spec->enums =
    578       _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
    579    spec->access_cache =
    580       _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
    581 
    582    return spec;
    583 }
    584 
    585 struct gen_spec *
    586 gen_spec_load(const struct gen_device_info *devinfo)
    587 {
    588    struct parser_context ctx;
    589    void *buf;
    590    uint8_t *text_data = NULL;
    591    uint32_t text_offset = 0, text_length = 0;
    592    MAYBE_UNUSED uint32_t total_length;
    593    uint32_t gen_10 = devinfo_to_gen(devinfo, true);
    594 
    595    for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) {
    596       if (genxml_files_table[i].gen_10 == gen_10) {
    597          text_offset = genxml_files_table[i].offset;
    598          text_length = genxml_files_table[i].length;
    599          break;
    600       }
    601    }
    602 
    603    if (text_length == 0) {
    604       fprintf(stderr, "unable to find gen (%u) data\n", gen_10);
    605       return NULL;
    606    }
    607 
    608    memset(&ctx, 0, sizeof ctx);
    609    ctx.parser = XML_ParserCreate(NULL);
    610    XML_SetUserData(ctx.parser, &ctx);
    611    if (ctx.parser == NULL) {
    612       fprintf(stderr, "failed to create parser\n");
    613       return NULL;
    614    }
    615 
    616    XML_SetElementHandler(ctx.parser, start_element, end_element);
    617    XML_SetCharacterDataHandler(ctx.parser, character_data);
    618 
    619    ctx.spec = gen_spec_init();
    620    if (ctx.spec == NULL) {
    621       fprintf(stderr, "Failed to create gen_spec\n");
    622       return NULL;
    623    }
    624 
    625    total_length = zlib_inflate(compress_genxmls,
    626                                sizeof(compress_genxmls),
    627                                (void **) &text_data);
    628    assert(text_offset + text_length <= total_length);
    629 
    630    buf = XML_GetBuffer(ctx.parser, text_length);
    631    memcpy(buf, &text_data[text_offset], text_length);
    632 
    633    if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) {
    634       fprintf(stderr,
    635               "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
    636               XML_GetCurrentLineNumber(ctx.parser),
    637               XML_GetCurrentColumnNumber(ctx.parser),
    638               XML_GetCurrentByteIndex(ctx.parser), text_length,
    639               XML_ErrorString(XML_GetErrorCode(ctx.parser)));
    640       XML_ParserFree(ctx.parser);
    641       free(text_data);
    642       return NULL;
    643    }
    644 
    645    XML_ParserFree(ctx.parser);
    646    free(text_data);
    647 
    648    return ctx.spec;
    649 }
    650 
    651 struct gen_spec *
    652 gen_spec_load_from_path(const struct gen_device_info *devinfo,
    653                         const char *path)
    654 {
    655    struct parser_context ctx;
    656    size_t len, filename_len = strlen(path) + 20;
    657    char *filename = malloc(filename_len);
    658    void *buf;
    659    FILE *input;
    660 
    661    len = snprintf(filename, filename_len, "%s/gen%i.xml",
    662                   path, devinfo_to_gen(devinfo, false));
    663    assert(len < filename_len);
    664 
    665    input = fopen(filename, "r");
    666    if (input == NULL) {
    667       fprintf(stderr, "failed to open xml description\n");
    668       free(filename);
    669       return NULL;
    670    }
    671 
    672    memset(&ctx, 0, sizeof ctx);
    673    ctx.parser = XML_ParserCreate(NULL);
    674    XML_SetUserData(ctx.parser, &ctx);
    675    if (ctx.parser == NULL) {
    676       fprintf(stderr, "failed to create parser\n");
    677       fclose(input);
    678       free(filename);
    679       return NULL;
    680    }
    681 
    682    XML_SetElementHandler(ctx.parser, start_element, end_element);
    683    XML_SetCharacterDataHandler(ctx.parser, character_data);
    684    ctx.loc.filename = filename;
    685 
    686    ctx.spec = gen_spec_init();
    687    if (ctx.spec == NULL) {
    688       fprintf(stderr, "Failed to create gen_spec\n");
    689       goto end;
    690    }
    691 
    692    do {
    693       buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
    694       len = fread(buf, 1, XML_BUFFER_SIZE, input);
    695       if (ferror(input)) {
    696          fprintf(stderr, "fread: %m\n");
    697          gen_spec_destroy(ctx.spec);
    698          ctx.spec = NULL;
    699          goto end;
    700       } else if (feof(input))
    701          goto end;
    702 
    703       if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
    704          fprintf(stderr,
    705                  "Error parsing XML at line %ld col %ld: %s\n",
    706                  XML_GetCurrentLineNumber(ctx.parser),
    707                  XML_GetCurrentColumnNumber(ctx.parser),
    708                  XML_ErrorString(XML_GetErrorCode(ctx.parser)));
    709          gen_spec_destroy(ctx.spec);
    710          ctx.spec = NULL;
    711          goto end;
    712       }
    713    } while (len > 0);
    714 
    715  end:
    716    XML_ParserFree(ctx.parser);
    717 
    718    fclose(input);
    719    free(filename);
    720 
    721    /* free ctx.spec if genxml is empty */
    722    if (ctx.spec && _mesa_hash_table_num_entries(ctx.spec->commands) == 0) {
    723       gen_spec_destroy(ctx.spec);
    724       return NULL;
    725    }
    726 
    727    return ctx.spec;
    728 }
    729 
    730 void gen_spec_destroy(struct gen_spec *spec)
    731 {
    732    ralloc_free(spec);
    733 }
    734 
    735 struct gen_group *
    736 gen_spec_find_instruction(struct gen_spec *spec,
    737                           enum drm_i915_gem_engine_class engine,
    738                           const uint32_t *p)
    739 {
    740    hash_table_foreach(spec->commands, entry) {
    741       struct gen_group *command = entry->data;
    742       uint32_t opcode = *p & command->opcode_mask;
    743       if ((command->engine_mask & I915_ENGINE_CLASS_TO_MASK(engine)) &&
    744            opcode == command->opcode)
    745          return command;
    746    }
    747 
    748    return NULL;
    749 }
    750 
    751 struct gen_field *
    752 gen_group_find_field(struct gen_group *group, const char *name)
    753 {
    754    char path[256];
    755    snprintf(path, sizeof(path), "%s/%s", group->name, name);
    756 
    757    struct gen_spec *spec = group->spec;
    758    struct hash_entry *entry = _mesa_hash_table_search(spec->access_cache,
    759                                                       path);
    760    if (entry)
    761       return entry->data;
    762 
    763    struct gen_field *field = group->fields;
    764    while (field) {
    765       if (strcmp(field->name, name) == 0) {
    766          _mesa_hash_table_insert(spec->access_cache,
    767                                  ralloc_strdup(spec, path),
    768                                  field);
    769          return field;
    770       }
    771       field = field->next;
    772    }
    773 
    774    return NULL;
    775 }
    776 
    777 int
    778 gen_group_get_length(struct gen_group *group, const uint32_t *p)
    779 {
    780    if (group) {
    781       if (group->fixed_length)
    782          return group->dw_length;
    783       else {
    784          struct gen_field *field = group->dword_length_field;
    785          if (field) {
    786             return field_value(p[0], field->start, field->end) + group->bias;
    787          }
    788       }
    789    }
    790 
    791    uint32_t h = p[0];
    792    uint32_t type = field_value(h, 29, 31);
    793 
    794    switch (type) {
    795    case 0: /* MI */ {
    796       uint32_t opcode = field_value(h, 23, 28);
    797       if (opcode < 16)
    798          return 1;
    799       else
    800          return field_value(h, 0, 7) + 2;
    801       break;
    802    }
    803 
    804    case 2: /* BLT */ {
    805       return field_value(h, 0, 7) + 2;
    806    }
    807 
    808    case 3: /* Render */ {
    809       uint32_t subtype = field_value(h, 27, 28);
    810       uint32_t opcode = field_value(h, 24, 26);
    811       uint16_t whole_opcode = field_value(h, 16, 31);
    812       switch (subtype) {
    813       case 0:
    814          if (whole_opcode == 0x6104 /* PIPELINE_SELECT_965 */)
    815             return 1;
    816          else if (opcode < 2)
    817             return field_value(h, 0, 7) + 2;
    818          else
    819             return -1;
    820       case 1:
    821          if (opcode < 2)
    822             return 1;
    823          else
    824             return -1;
    825       case 2: {
    826          if (opcode == 0)
    827             return field_value(h, 0, 7) + 2;
    828          else if (opcode < 3)
    829             return field_value(h, 0, 15) + 2;
    830          else
    831             return -1;
    832       }
    833       case 3:
    834          if (whole_opcode == 0x780b)
    835             return 1;
    836          else if (opcode < 4)
    837             return field_value(h, 0, 7) + 2;
    838          else
    839             return -1;
    840       }
    841    }
    842    }
    843 
    844    return -1;
    845 }
    846 
    847 static const char *
    848 gen_get_enum_name(struct gen_enum *e, uint64_t value)
    849 {
    850    for (int i = 0; i < e->nvalues; i++) {
    851       if (e->values[i]->value == value) {
    852          return e->values[i]->name;
    853       }
    854    }
    855    return NULL;
    856 }
    857 
    858 static bool
    859 iter_more_fields(const struct gen_field_iterator *iter)
    860 {
    861    return iter->field != NULL && iter->field->next != NULL;
    862 }
    863 
    864 static uint32_t
    865 iter_group_offset_bits(const struct gen_field_iterator *iter,
    866                        uint32_t group_iter)
    867 {
    868    return iter->group->group_offset + (group_iter * iter->group->group_size);
    869 }
    870 
    871 static bool
    872 iter_more_groups(const struct gen_field_iterator *iter)
    873 {
    874    if (iter->group->variable) {
    875       int length = gen_group_get_length(iter->group, iter->p);
    876       assert(length >= 0 && "error the length is unknown!");
    877       return iter_group_offset_bits(iter, iter->group_iter + 1) <
    878               (length * 32);
    879    } else {
    880       return (iter->group_iter + 1) < iter->group->group_count ||
    881          iter->group->next != NULL;
    882    }
    883 }
    884 
    885 static void
    886 iter_start_field(struct gen_field_iterator *iter, struct gen_field *field)
    887 {
    888    iter->field = field;
    889 
    890    int group_member_offset = iter_group_offset_bits(iter, iter->group_iter);
    891 
    892    iter->start_bit = group_member_offset + iter->field->start;
    893    iter->end_bit = group_member_offset + iter->field->end;
    894    iter->struct_desc = NULL;
    895 }
    896 
    897 static void
    898 iter_advance_group(struct gen_field_iterator *iter)
    899 {
    900    if (iter->group->variable)
    901       iter->group_iter++;
    902    else {
    903       if ((iter->group_iter + 1) < iter->group->group_count) {
    904          iter->group_iter++;
    905       } else {
    906          iter->group = iter->group->next;
    907          iter->group_iter = 0;
    908       }
    909    }
    910 
    911    iter_start_field(iter, iter->group->fields);
    912 }
    913 
    914 static bool
    915 iter_advance_field(struct gen_field_iterator *iter)
    916 {
    917    if (iter_more_fields(iter)) {
    918       iter_start_field(iter, iter->field->next);
    919    } else {
    920       if (!iter_more_groups(iter))
    921          return false;
    922 
    923       iter_advance_group(iter);
    924    }
    925    return true;
    926 }
    927 
    928 static bool
    929 iter_decode_field_raw(struct gen_field_iterator *iter, uint64_t *qw)
    930 {
    931    *qw = 0;
    932 
    933    int field_start = iter->p_bit + iter->start_bit;
    934    int field_end = iter->p_bit + iter->end_bit;
    935 
    936    const uint32_t *p = iter->p + (iter->start_bit / 32);
    937    if (iter->p_end && p >= iter->p_end)
    938       return false;
    939 
    940    if ((field_end - field_start) > 32) {
    941       if (!iter->p_end || (p + 1) < iter->p_end)
    942          *qw = ((uint64_t) p[1]) << 32;
    943       *qw |= p[0];
    944    } else
    945       *qw = p[0];
    946 
    947    *qw = field_value(*qw, field_start, field_end);
    948 
    949    /* Address & offset types have to be aligned to dwords, their start bit is
    950     * a reminder of the alignment requirement.
    951     */
    952    if (iter->field->type.kind == GEN_TYPE_ADDRESS ||
    953        iter->field->type.kind == GEN_TYPE_OFFSET)
    954       *qw <<= field_start % 32;
    955 
    956    return true;
    957 }
    958 
    959 static bool
    960 iter_decode_field(struct gen_field_iterator *iter)
    961 {
    962    union {
    963       uint64_t qw;
    964       float f;
    965    } v;
    966 
    967    if (iter->field->name)
    968       snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name);
    969    else
    970       memset(iter->name, 0, sizeof(iter->name));
    971 
    972    memset(&v, 0, sizeof(v));
    973 
    974    if (!iter_decode_field_raw(iter, &iter->raw_value))
    975       return false;
    976 
    977    const char *enum_name = NULL;
    978 
    979    v.qw = iter->raw_value;
    980    switch (iter->field->type.kind) {
    981    case GEN_TYPE_UNKNOWN:
    982    case GEN_TYPE_INT: {
    983       snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw);
    984       enum_name = gen_get_enum_name(&iter->field->inline_enum, v.qw);
    985       break;
    986    }
    987    case GEN_TYPE_UINT: {
    988       snprintf(iter->value, sizeof(iter->value), "%"PRIu64, v.qw);
    989       enum_name = gen_get_enum_name(&iter->field->inline_enum, v.qw);
    990       break;
    991    }
    992    case GEN_TYPE_BOOL: {
    993       const char *true_string =
    994          iter->print_colors ? "\e[0;35mtrue\e[0m" : "true";
    995       snprintf(iter->value, sizeof(iter->value), "%s",
    996                v.qw ? true_string : "false");
    997       break;
    998    }
    999    case GEN_TYPE_FLOAT:
   1000       snprintf(iter->value, sizeof(iter->value), "%f", v.f);
   1001       break;
   1002    case GEN_TYPE_ADDRESS:
   1003    case GEN_TYPE_OFFSET:
   1004       snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, v.qw);
   1005       break;
   1006    case GEN_TYPE_STRUCT:
   1007       snprintf(iter->value, sizeof(iter->value), "<struct %s>",
   1008                iter->field->type.gen_struct->name);
   1009       iter->struct_desc =
   1010          gen_spec_find_struct(iter->group->spec,
   1011                               iter->field->type.gen_struct->name);
   1012       break;
   1013    case GEN_TYPE_UFIXED:
   1014       snprintf(iter->value, sizeof(iter->value), "%f",
   1015                (float) v.qw / (1 << iter->field->type.f));
   1016       break;
   1017    case GEN_TYPE_SFIXED: {
   1018       /* Sign extend before converting */
   1019       int bits = iter->field->type.i + iter->field->type.f + 1;
   1020       int64_t v_sign_extend = ((int64_t)(v.qw << (64 - bits))) >> (64 - bits);
   1021       snprintf(iter->value, sizeof(iter->value), "%f",
   1022                (float) v_sign_extend / (1 << iter->field->type.f));
   1023       break;
   1024    }
   1025    case GEN_TYPE_MBO:
   1026        break;
   1027    case GEN_TYPE_ENUM: {
   1028       snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw);
   1029       enum_name = gen_get_enum_name(iter->field->type.gen_enum, v.qw);
   1030       break;
   1031    }
   1032    }
   1033 
   1034    if (strlen(iter->group->name) == 0) {
   1035       int length = strlen(iter->name);
   1036       snprintf(iter->name + length, sizeof(iter->name) - length,
   1037                "[%i]", iter->group_iter);
   1038    }
   1039 
   1040    if (enum_name) {
   1041       int length = strlen(iter->value);
   1042       snprintf(iter->value + length, sizeof(iter->value) - length,
   1043                " (%s)", enum_name);
   1044    } else if (strcmp(iter->name, "Surface Format") == 0 ||
   1045               strcmp(iter->name, "Source Element Format") == 0) {
   1046       if (isl_format_is_valid((enum isl_format)v.qw)) {
   1047          const char *fmt_name = isl_format_get_name((enum isl_format)v.qw);
   1048          int length = strlen(iter->value);
   1049          snprintf(iter->value + length, sizeof(iter->value) - length,
   1050                   " (%s)", fmt_name);
   1051       }
   1052    }
   1053 
   1054    return true;
   1055 }
   1056 
   1057 void
   1058 gen_field_iterator_init(struct gen_field_iterator *iter,
   1059                         struct gen_group *group,
   1060                         const uint32_t *p, int p_bit,
   1061                         bool print_colors)
   1062 {
   1063    memset(iter, 0, sizeof(*iter));
   1064 
   1065    iter->group = group;
   1066    iter->p = p;
   1067    iter->p_bit = p_bit;
   1068 
   1069    int length = gen_group_get_length(iter->group, iter->p);
   1070    assert(length >= 0 && "error the length is unknown!");
   1071    iter->p_end = length >= 0 ? &p[length] : NULL;
   1072    iter->print_colors = print_colors;
   1073 }
   1074 
   1075 bool
   1076 gen_field_iterator_next(struct gen_field_iterator *iter)
   1077 {
   1078    /* Initial condition */
   1079    if (!iter->field) {
   1080       if (iter->group->fields)
   1081          iter_start_field(iter, iter->group->fields);
   1082       else
   1083          iter_start_field(iter, iter->group->next->fields);
   1084 
   1085       bool result = iter_decode_field(iter);
   1086       if (!result && iter->p_end) {
   1087          /* We're dealing with a non empty struct of length=0 (BLEND_STATE on
   1088           * Gen 7.5)
   1089           */
   1090          assert(iter->group->dw_length == 0);
   1091       }
   1092 
   1093       return result;
   1094    }
   1095 
   1096    if (!iter_advance_field(iter))
   1097       return false;
   1098 
   1099    if (!iter_decode_field(iter))
   1100       return false;
   1101 
   1102    return true;
   1103 }
   1104 
   1105 static void
   1106 print_dword_header(FILE *outfile,
   1107                    struct gen_field_iterator *iter,
   1108                    uint64_t offset, uint32_t dword)
   1109 {
   1110    fprintf(outfile, "0x%08"PRIx64":  0x%08x : Dword %d\n",
   1111            offset + 4 * dword, iter->p[dword], dword);
   1112 }
   1113 
   1114 bool
   1115 gen_field_is_header(struct gen_field *field)
   1116 {
   1117    uint32_t bits;
   1118 
   1119    if (field->start >= 32)
   1120       return false;
   1121 
   1122    bits = (1U << (field->end - field->start + 1)) - 1;
   1123    bits <<= field->start;
   1124 
   1125    return (field->parent->opcode_mask & bits) != 0;
   1126 }
   1127 
   1128 void
   1129 gen_print_group(FILE *outfile, struct gen_group *group, uint64_t offset,
   1130                 const uint32_t *p, int p_bit, bool color)
   1131 {
   1132    struct gen_field_iterator iter;
   1133    int last_dword = -1;
   1134 
   1135    gen_field_iterator_init(&iter, group, p, p_bit, color);
   1136    while (gen_field_iterator_next(&iter)) {
   1137       int iter_dword = iter.end_bit / 32;
   1138       if (last_dword != iter_dword) {
   1139          for (int i = last_dword + 1; i <= iter_dword; i++)
   1140             print_dword_header(outfile, &iter, offset, i);
   1141          last_dword = iter_dword;
   1142       }
   1143       if (!gen_field_is_header(iter.field)) {
   1144          fprintf(outfile, "    %s: %s\n", iter.name, iter.value);
   1145          if (iter.struct_desc) {
   1146             int struct_dword = iter.start_bit / 32;
   1147             uint64_t struct_offset = offset + 4 * struct_dword;
   1148             gen_print_group(outfile, iter.struct_desc, struct_offset,
   1149                             &p[struct_dword], iter.start_bit % 32, color);
   1150          }
   1151       }
   1152    }
   1153 }
   1154