1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdio.h> 25bf215546Sopenharmony_ci#include <stdbool.h> 26bf215546Sopenharmony_ci#include <stdint.h> 27bf215546Sopenharmony_ci#include <stdarg.h> 28bf215546Sopenharmony_ci#include <string.h> 29bf215546Sopenharmony_ci#include <expat.h> 30bf215546Sopenharmony_ci#include <inttypes.h> 31bf215546Sopenharmony_ci#include <zlib.h> 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include <util/macros.h> 34bf215546Sopenharmony_ci#include <util/ralloc.h> 35bf215546Sopenharmony_ci#include <util/u_math.h> 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "intel_decoder.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "isl/isl.h" 40bf215546Sopenharmony_ci#include "genxml/genX_xml.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#define XML_BUFFER_SIZE 4096 43bf215546Sopenharmony_ci#define MAX_VALUE_ITEMS 128 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistruct location { 46bf215546Sopenharmony_ci const char *filename; 47bf215546Sopenharmony_ci int line_number; 48bf215546Sopenharmony_ci}; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistruct parser_context { 51bf215546Sopenharmony_ci XML_Parser parser; 52bf215546Sopenharmony_ci int foo; 53bf215546Sopenharmony_ci struct location loc; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci struct intel_group *group; 56bf215546Sopenharmony_ci struct intel_enum *enoom; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci int n_values, n_allocated_values; 59bf215546Sopenharmony_ci struct intel_value **values; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci struct intel_field *last_field; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci struct intel_spec *spec; 64bf215546Sopenharmony_ci}; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ciconst char * 67bf215546Sopenharmony_ciintel_group_get_name(struct intel_group *group) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci return group->name; 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ciuint32_t 73bf215546Sopenharmony_ciintel_group_get_opcode(struct intel_group *group) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci return group->opcode; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistruct intel_group * 79bf215546Sopenharmony_ciintel_spec_find_struct(struct intel_spec *spec, const char *name) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search(spec->structs, 82bf215546Sopenharmony_ci name); 83bf215546Sopenharmony_ci return entry ? entry->data : NULL; 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistruct intel_group * 87bf215546Sopenharmony_ciintel_spec_find_register(struct intel_spec *spec, uint32_t offset) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci struct hash_entry *entry = 90bf215546Sopenharmony_ci _mesa_hash_table_search(spec->registers_by_offset, 91bf215546Sopenharmony_ci (void *) (uintptr_t) offset); 92bf215546Sopenharmony_ci return entry ? entry->data : NULL; 93bf215546Sopenharmony_ci} 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_cistruct intel_group * 96bf215546Sopenharmony_ciintel_spec_find_register_by_name(struct intel_spec *spec, const char *name) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci struct hash_entry *entry = 99bf215546Sopenharmony_ci _mesa_hash_table_search(spec->registers_by_name, name); 100bf215546Sopenharmony_ci return entry ? entry->data : NULL; 101bf215546Sopenharmony_ci} 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_cistruct intel_enum * 104bf215546Sopenharmony_ciintel_spec_find_enum(struct intel_spec *spec, const char *name) 105bf215546Sopenharmony_ci{ 106bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search(spec->enums, 107bf215546Sopenharmony_ci name); 108bf215546Sopenharmony_ci return entry ? entry->data : NULL; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ciuint32_t 112bf215546Sopenharmony_ciintel_spec_get_gen(struct intel_spec *spec) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci return spec->gen; 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic void __attribute__((noreturn)) 118bf215546Sopenharmony_cifail(struct location *loc, const char *msg, ...) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci va_list ap; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci va_start(ap, msg); 123bf215546Sopenharmony_ci fprintf(stderr, "%s:%d: error: ", 124bf215546Sopenharmony_ci loc->filename, loc->line_number); 125bf215546Sopenharmony_ci vfprintf(stderr, msg, ap); 126bf215546Sopenharmony_ci fprintf(stderr, "\n"); 127bf215546Sopenharmony_ci va_end(ap); 128bf215546Sopenharmony_ci exit(EXIT_FAILURE); 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic void 132bf215546Sopenharmony_ciget_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count, 133bf215546Sopenharmony_ci uint32_t *size, bool *variable) 134bf215546Sopenharmony_ci{ 135bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 136bf215546Sopenharmony_ci char *p; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (strcmp(atts[i], "count") == 0) { 139bf215546Sopenharmony_ci *count = strtoul(atts[i + 1], &p, 0); 140bf215546Sopenharmony_ci if (*count == 0) 141bf215546Sopenharmony_ci *variable = true; 142bf215546Sopenharmony_ci } else if (strcmp(atts[i], "start") == 0) { 143bf215546Sopenharmony_ci *offset = strtoul(atts[i + 1], &p, 0); 144bf215546Sopenharmony_ci } else if (strcmp(atts[i], "size") == 0) { 145bf215546Sopenharmony_ci *size = strtoul(atts[i + 1], &p, 0); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci return; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic struct intel_group * 152bf215546Sopenharmony_cicreate_group(struct parser_context *ctx, 153bf215546Sopenharmony_ci const char *name, 154bf215546Sopenharmony_ci const char **atts, 155bf215546Sopenharmony_ci struct intel_group *parent, 156bf215546Sopenharmony_ci bool fixed_length) 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci struct intel_group *group; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci group = rzalloc(ctx->spec, struct intel_group); 161bf215546Sopenharmony_ci if (name) 162bf215546Sopenharmony_ci group->name = ralloc_strdup(group, name); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci group->spec = ctx->spec; 165bf215546Sopenharmony_ci group->variable = false; 166bf215546Sopenharmony_ci group->fixed_length = fixed_length; 167bf215546Sopenharmony_ci group->dword_length_field = NULL; 168bf215546Sopenharmony_ci group->dw_length = 0; 169bf215546Sopenharmony_ci group->engine_mask = I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER) | 170bf215546Sopenharmony_ci I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO) | 171bf215546Sopenharmony_ci I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY); 172bf215546Sopenharmony_ci group->bias = 1; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 175bf215546Sopenharmony_ci char *p; 176bf215546Sopenharmony_ci if (strcmp(atts[i], "length") == 0) { 177bf215546Sopenharmony_ci group->dw_length = strtoul(atts[i + 1], &p, 0); 178bf215546Sopenharmony_ci } else if (strcmp(atts[i], "bias") == 0) { 179bf215546Sopenharmony_ci group->bias = strtoul(atts[i + 1], &p, 0); 180bf215546Sopenharmony_ci } else if (strcmp(atts[i], "engine") == 0) { 181bf215546Sopenharmony_ci void *mem_ctx = ralloc_context(NULL); 182bf215546Sopenharmony_ci char *tmp = ralloc_strdup(mem_ctx, atts[i + 1]); 183bf215546Sopenharmony_ci char *save_ptr; 184bf215546Sopenharmony_ci char *tok = strtok_r(tmp, "|", &save_ptr); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci group->engine_mask = 0; 187bf215546Sopenharmony_ci while (tok != NULL) { 188bf215546Sopenharmony_ci if (strcmp(tok, "render") == 0) { 189bf215546Sopenharmony_ci group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER); 190bf215546Sopenharmony_ci } else if (strcmp(tok, "video") == 0) { 191bf215546Sopenharmony_ci group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO); 192bf215546Sopenharmony_ci } else if (strcmp(tok, "blitter") == 0) { 193bf215546Sopenharmony_ci group->engine_mask |= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY); 194bf215546Sopenharmony_ci } else { 195bf215546Sopenharmony_ci fprintf(stderr, "unknown engine class defined for instruction \"%s\": %s\n", name, atts[i + 1]); 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci tok = strtok_r(NULL, "|", &save_ptr); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci ralloc_free(mem_ctx); 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci if (parent) { 206bf215546Sopenharmony_ci group->parent = parent; 207bf215546Sopenharmony_ci get_array_offset_count(atts, 208bf215546Sopenharmony_ci &group->array_offset, 209bf215546Sopenharmony_ci &group->array_count, 210bf215546Sopenharmony_ci &group->array_item_size, 211bf215546Sopenharmony_ci &group->variable); 212bf215546Sopenharmony_ci } 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci return group; 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_cistatic struct intel_enum * 218bf215546Sopenharmony_cicreate_enum(struct parser_context *ctx, const char *name, const char **atts) 219bf215546Sopenharmony_ci{ 220bf215546Sopenharmony_ci struct intel_enum *e; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci e = rzalloc(ctx->spec, struct intel_enum); 223bf215546Sopenharmony_ci if (name) 224bf215546Sopenharmony_ci e->name = ralloc_strdup(e, name); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci return e; 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cistatic void 230bf215546Sopenharmony_ciget_register_offset(const char **atts, uint32_t *offset) 231bf215546Sopenharmony_ci{ 232bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 233bf215546Sopenharmony_ci char *p; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci if (strcmp(atts[i], "num") == 0) 236bf215546Sopenharmony_ci *offset = strtoul(atts[i + 1], &p, 0); 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci return; 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_cistatic void 242bf215546Sopenharmony_ciget_start_end_pos(int *start, int *end) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci /* start value has to be mod with 32 as we need the relative 245bf215546Sopenharmony_ci * start position in the first DWord. For the end position, add 246bf215546Sopenharmony_ci * the length of the field to the start position to get the 247bf215546Sopenharmony_ci * relative position in the 64 bit address. 248bf215546Sopenharmony_ci */ 249bf215546Sopenharmony_ci if (*end - *start > 32) { 250bf215546Sopenharmony_ci int len = *end - *start; 251bf215546Sopenharmony_ci *start = *start % 32; 252bf215546Sopenharmony_ci *end = *start + len; 253bf215546Sopenharmony_ci } else { 254bf215546Sopenharmony_ci *start = *start % 32; 255bf215546Sopenharmony_ci *end = *end % 32; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci return; 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_cistatic inline uint64_t 262bf215546Sopenharmony_cimask(int start, int end) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci uint64_t v; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci v = ~0ULL >> (63 - end + start); 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci return v << start; 269bf215546Sopenharmony_ci} 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_cistatic inline uint64_t 272bf215546Sopenharmony_cifield_value(uint64_t value, int start, int end) 273bf215546Sopenharmony_ci{ 274bf215546Sopenharmony_ci get_start_end_pos(&start, &end); 275bf215546Sopenharmony_ci return (value & mask(start, end)) >> (start); 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_cistatic struct intel_type 279bf215546Sopenharmony_cistring_to_type(struct parser_context *ctx, const char *s) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci int i, f; 282bf215546Sopenharmony_ci struct intel_group *g; 283bf215546Sopenharmony_ci struct intel_enum *e; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (strcmp(s, "int") == 0) 286bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_INT }; 287bf215546Sopenharmony_ci else if (strcmp(s, "uint") == 0) 288bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_UINT }; 289bf215546Sopenharmony_ci else if (strcmp(s, "bool") == 0) 290bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_BOOL }; 291bf215546Sopenharmony_ci else if (strcmp(s, "float") == 0) 292bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_FLOAT }; 293bf215546Sopenharmony_ci else if (strcmp(s, "address") == 0) 294bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_ADDRESS }; 295bf215546Sopenharmony_ci else if (strcmp(s, "offset") == 0) 296bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_OFFSET }; 297bf215546Sopenharmony_ci else if (sscanf(s, "u%d.%d", &i, &f) == 2) 298bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_UFIXED, .i = i, .f = f }; 299bf215546Sopenharmony_ci else if (sscanf(s, "s%d.%d", &i, &f) == 2) 300bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_SFIXED, .i = i, .f = f }; 301bf215546Sopenharmony_ci else if (g = intel_spec_find_struct(ctx->spec, s), g != NULL) 302bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_STRUCT, .intel_struct = g }; 303bf215546Sopenharmony_ci else if (e = intel_spec_find_enum(ctx->spec, s), e != NULL) 304bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_ENUM, .intel_enum = e }; 305bf215546Sopenharmony_ci else if (strcmp(s, "mbo") == 0) 306bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_MBO }; 307bf215546Sopenharmony_ci else if (strcmp(s, "mbz") == 0) 308bf215546Sopenharmony_ci return (struct intel_type) { .kind = INTEL_TYPE_MBZ }; 309bf215546Sopenharmony_ci else 310bf215546Sopenharmony_ci fail(&ctx->loc, "invalid type: %s", s); 311bf215546Sopenharmony_ci} 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_cistatic struct intel_field * 314bf215546Sopenharmony_cicreate_field(struct parser_context *ctx, const char **atts) 315bf215546Sopenharmony_ci{ 316bf215546Sopenharmony_ci struct intel_field *field; 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci field = rzalloc(ctx->group, struct intel_field); 319bf215546Sopenharmony_ci field->parent = ctx->group; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 322bf215546Sopenharmony_ci char *p; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci if (strcmp(atts[i], "name") == 0) { 325bf215546Sopenharmony_ci field->name = ralloc_strdup(field, atts[i + 1]); 326bf215546Sopenharmony_ci if (strcmp(field->name, "DWord Length") == 0) { 327bf215546Sopenharmony_ci field->parent->dword_length_field = field; 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci } else if (strcmp(atts[i], "start") == 0) { 330bf215546Sopenharmony_ci field->start = strtoul(atts[i + 1], &p, 0); 331bf215546Sopenharmony_ci } else if (strcmp(atts[i], "end") == 0) { 332bf215546Sopenharmony_ci field->end = strtoul(atts[i + 1], &p, 0); 333bf215546Sopenharmony_ci } else if (strcmp(atts[i], "type") == 0) { 334bf215546Sopenharmony_ci field->type = string_to_type(ctx, atts[i + 1]); 335bf215546Sopenharmony_ci } else if (strcmp(atts[i], "default") == 0 && 336bf215546Sopenharmony_ci field->start >= 16 && field->end <= 31) { 337bf215546Sopenharmony_ci field->has_default = true; 338bf215546Sopenharmony_ci field->default_value = strtoul(atts[i + 1], &p, 0); 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci return field; 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_cistatic struct intel_field * 346bf215546Sopenharmony_cicreate_array_field(struct parser_context *ctx, struct intel_group *array) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci struct intel_field *field; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci field = rzalloc(ctx->group, struct intel_field); 351bf215546Sopenharmony_ci field->parent = ctx->group; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci field->array = array; 354bf215546Sopenharmony_ci field->start = field->array->array_offset; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci return field; 357bf215546Sopenharmony_ci} 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_cistatic struct intel_value * 360bf215546Sopenharmony_cicreate_value(struct parser_context *ctx, const char **atts) 361bf215546Sopenharmony_ci{ 362bf215546Sopenharmony_ci struct intel_value *value = rzalloc(ctx->values, struct intel_value); 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 365bf215546Sopenharmony_ci if (strcmp(atts[i], "name") == 0) 366bf215546Sopenharmony_ci value->name = ralloc_strdup(value, atts[i + 1]); 367bf215546Sopenharmony_ci else if (strcmp(atts[i], "value") == 0) 368bf215546Sopenharmony_ci value->value = strtoul(atts[i + 1], NULL, 0); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci return value; 372bf215546Sopenharmony_ci} 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_cistatic struct intel_field * 375bf215546Sopenharmony_cicreate_and_append_field(struct parser_context *ctx, 376bf215546Sopenharmony_ci const char **atts, 377bf215546Sopenharmony_ci struct intel_group *array) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci struct intel_field *field = array ? 380bf215546Sopenharmony_ci create_array_field(ctx, array) : create_field(ctx, atts); 381bf215546Sopenharmony_ci struct intel_field *prev = NULL, *list = ctx->group->fields; 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci while (list && field->start > list->start) { 384bf215546Sopenharmony_ci prev = list; 385bf215546Sopenharmony_ci list = list->next; 386bf215546Sopenharmony_ci } 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci field->next = list; 389bf215546Sopenharmony_ci if (prev == NULL) 390bf215546Sopenharmony_ci ctx->group->fields = field; 391bf215546Sopenharmony_ci else 392bf215546Sopenharmony_ci prev->next = field; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci return field; 395bf215546Sopenharmony_ci} 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_cistatic void 398bf215546Sopenharmony_cistart_element(void *data, const char *element_name, const char **atts) 399bf215546Sopenharmony_ci{ 400bf215546Sopenharmony_ci struct parser_context *ctx = data; 401bf215546Sopenharmony_ci const char *name = NULL; 402bf215546Sopenharmony_ci const char *gen = NULL; 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci for (int i = 0; atts[i]; i += 2) { 407bf215546Sopenharmony_ci if (strcmp(atts[i], "name") == 0) 408bf215546Sopenharmony_ci name = atts[i + 1]; 409bf215546Sopenharmony_ci else if (strcmp(atts[i], "gen") == 0) 410bf215546Sopenharmony_ci gen = atts[i + 1]; 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci if (strcmp(element_name, "genxml") == 0) { 414bf215546Sopenharmony_ci if (name == NULL) 415bf215546Sopenharmony_ci fail(&ctx->loc, "no platform name given"); 416bf215546Sopenharmony_ci if (gen == NULL) 417bf215546Sopenharmony_ci fail(&ctx->loc, "no gen given"); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci int major, minor; 420bf215546Sopenharmony_ci int n = sscanf(gen, "%d.%d", &major, &minor); 421bf215546Sopenharmony_ci if (n == 0) 422bf215546Sopenharmony_ci fail(&ctx->loc, "invalid gen given: %s", gen); 423bf215546Sopenharmony_ci if (n == 1) 424bf215546Sopenharmony_ci minor = 0; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci ctx->spec->gen = intel_make_gen(major, minor); 427bf215546Sopenharmony_ci } else if (strcmp(element_name, "instruction") == 0) { 428bf215546Sopenharmony_ci ctx->group = create_group(ctx, name, atts, NULL, false); 429bf215546Sopenharmony_ci } else if (strcmp(element_name, "struct") == 0) { 430bf215546Sopenharmony_ci ctx->group = create_group(ctx, name, atts, NULL, true); 431bf215546Sopenharmony_ci } else if (strcmp(element_name, "register") == 0) { 432bf215546Sopenharmony_ci ctx->group = create_group(ctx, name, atts, NULL, true); 433bf215546Sopenharmony_ci get_register_offset(atts, &ctx->group->register_offset); 434bf215546Sopenharmony_ci } else if (strcmp(element_name, "group") == 0) { 435bf215546Sopenharmony_ci struct intel_group *group = create_group(ctx, "", atts, ctx->group, false); 436bf215546Sopenharmony_ci ctx->last_field = create_and_append_field(ctx, NULL, group); 437bf215546Sopenharmony_ci ctx->group = group; 438bf215546Sopenharmony_ci } else if (strcmp(element_name, "field") == 0) { 439bf215546Sopenharmony_ci ctx->last_field = create_and_append_field(ctx, atts, NULL); 440bf215546Sopenharmony_ci } else if (strcmp(element_name, "enum") == 0) { 441bf215546Sopenharmony_ci ctx->enoom = create_enum(ctx, name, atts); 442bf215546Sopenharmony_ci } else if (strcmp(element_name, "value") == 0) { 443bf215546Sopenharmony_ci if (ctx->n_values >= ctx->n_allocated_values) { 444bf215546Sopenharmony_ci ctx->n_allocated_values = MAX2(2, ctx->n_allocated_values * 2); 445bf215546Sopenharmony_ci ctx->values = reralloc_array_size(ctx->spec, ctx->values, 446bf215546Sopenharmony_ci sizeof(struct intel_value *), 447bf215546Sopenharmony_ci ctx->n_allocated_values); 448bf215546Sopenharmony_ci } 449bf215546Sopenharmony_ci assert(ctx->n_values < ctx->n_allocated_values); 450bf215546Sopenharmony_ci ctx->values[ctx->n_values++] = create_value(ctx, atts); 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci} 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_cistatic void 456bf215546Sopenharmony_ciend_element(void *data, const char *name) 457bf215546Sopenharmony_ci{ 458bf215546Sopenharmony_ci struct parser_context *ctx = data; 459bf215546Sopenharmony_ci struct intel_spec *spec = ctx->spec; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci if (strcmp(name, "instruction") == 0 || 462bf215546Sopenharmony_ci strcmp(name, "struct") == 0 || 463bf215546Sopenharmony_ci strcmp(name, "register") == 0) { 464bf215546Sopenharmony_ci struct intel_group *group = ctx->group; 465bf215546Sopenharmony_ci struct intel_field *list = group->fields; 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci ctx->group = ctx->group->parent; 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci while (list && list->end <= 31) { 470bf215546Sopenharmony_ci if (list->start >= 16 && list->has_default) { 471bf215546Sopenharmony_ci group->opcode_mask |= 472bf215546Sopenharmony_ci mask(list->start % 32, list->end % 32); 473bf215546Sopenharmony_ci group->opcode |= list->default_value << list->start; 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci list = list->next; 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci if (strcmp(name, "instruction") == 0) 479bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->commands, group->name, group); 480bf215546Sopenharmony_ci else if (strcmp(name, "struct") == 0) 481bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->structs, group->name, group); 482bf215546Sopenharmony_ci else if (strcmp(name, "register") == 0) { 483bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->registers_by_name, group->name, group); 484bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->registers_by_offset, 485bf215546Sopenharmony_ci (void *) (uintptr_t) group->register_offset, 486bf215546Sopenharmony_ci group); 487bf215546Sopenharmony_ci } 488bf215546Sopenharmony_ci } else if (strcmp(name, "group") == 0) { 489bf215546Sopenharmony_ci ctx->group = ctx->group->parent; 490bf215546Sopenharmony_ci } else if (strcmp(name, "field") == 0) { 491bf215546Sopenharmony_ci struct intel_field *field = ctx->last_field; 492bf215546Sopenharmony_ci ctx->last_field = NULL; 493bf215546Sopenharmony_ci field->inline_enum.values = ctx->values; 494bf215546Sopenharmony_ci field->inline_enum.nvalues = ctx->n_values; 495bf215546Sopenharmony_ci ctx->values = ralloc_array(ctx->spec, struct intel_value*, ctx->n_allocated_values = 2); 496bf215546Sopenharmony_ci ctx->n_values = 0; 497bf215546Sopenharmony_ci } else if (strcmp(name, "enum") == 0) { 498bf215546Sopenharmony_ci struct intel_enum *e = ctx->enoom; 499bf215546Sopenharmony_ci e->values = ctx->values; 500bf215546Sopenharmony_ci e->nvalues = ctx->n_values; 501bf215546Sopenharmony_ci ctx->values = ralloc_array(ctx->spec, struct intel_value*, ctx->n_allocated_values = 2); 502bf215546Sopenharmony_ci ctx->n_values = 0; 503bf215546Sopenharmony_ci ctx->enoom = NULL; 504bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->enums, e->name, e); 505bf215546Sopenharmony_ci } 506bf215546Sopenharmony_ci} 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_cistatic void 509bf215546Sopenharmony_cicharacter_data(void *data, const XML_Char *s, int len) 510bf215546Sopenharmony_ci{ 511bf215546Sopenharmony_ci} 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_cistatic uint32_t zlib_inflate(const void *compressed_data, 514bf215546Sopenharmony_ci uint32_t compressed_len, 515bf215546Sopenharmony_ci void **out_ptr) 516bf215546Sopenharmony_ci{ 517bf215546Sopenharmony_ci struct z_stream_s zstream; 518bf215546Sopenharmony_ci void *out; 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci memset(&zstream, 0, sizeof(zstream)); 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci zstream.next_in = (unsigned char *)compressed_data; 523bf215546Sopenharmony_ci zstream.avail_in = compressed_len; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci if (inflateInit(&zstream) != Z_OK) 526bf215546Sopenharmony_ci return 0; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci out = malloc(4096); 529bf215546Sopenharmony_ci zstream.next_out = out; 530bf215546Sopenharmony_ci zstream.avail_out = 4096; 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci do { 533bf215546Sopenharmony_ci switch (inflate(&zstream, Z_SYNC_FLUSH)) { 534bf215546Sopenharmony_ci case Z_STREAM_END: 535bf215546Sopenharmony_ci goto end; 536bf215546Sopenharmony_ci case Z_OK: 537bf215546Sopenharmony_ci break; 538bf215546Sopenharmony_ci default: 539bf215546Sopenharmony_ci inflateEnd(&zstream); 540bf215546Sopenharmony_ci return 0; 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (zstream.avail_out) 544bf215546Sopenharmony_ci break; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci out = realloc(out, 2*zstream.total_out); 547bf215546Sopenharmony_ci if (out == NULL) { 548bf215546Sopenharmony_ci inflateEnd(&zstream); 549bf215546Sopenharmony_ci return 0; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci zstream.next_out = (unsigned char *)out + zstream.total_out; 553bf215546Sopenharmony_ci zstream.avail_out = zstream.total_out; 554bf215546Sopenharmony_ci } while (1); 555bf215546Sopenharmony_ci end: 556bf215546Sopenharmony_ci inflateEnd(&zstream); 557bf215546Sopenharmony_ci *out_ptr = out; 558bf215546Sopenharmony_ci return zstream.total_out; 559bf215546Sopenharmony_ci} 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_cistatic uint32_t _hash_uint32(const void *key) 562bf215546Sopenharmony_ci{ 563bf215546Sopenharmony_ci return (uint32_t) (uintptr_t) key; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_cistatic struct intel_spec * 567bf215546Sopenharmony_ciintel_spec_init(void) 568bf215546Sopenharmony_ci{ 569bf215546Sopenharmony_ci struct intel_spec *spec; 570bf215546Sopenharmony_ci spec = rzalloc(NULL, struct intel_spec); 571bf215546Sopenharmony_ci if (spec == NULL) 572bf215546Sopenharmony_ci return NULL; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci spec->commands = 575bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); 576bf215546Sopenharmony_ci spec->structs = 577bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); 578bf215546Sopenharmony_ci spec->registers_by_name = 579bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); 580bf215546Sopenharmony_ci spec->registers_by_offset = 581bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _hash_uint32, _mesa_key_pointer_equal); 582bf215546Sopenharmony_ci spec->enums = 583bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); 584bf215546Sopenharmony_ci spec->access_cache = 585bf215546Sopenharmony_ci _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal); 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci return spec; 588bf215546Sopenharmony_ci} 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_cistruct intel_spec * 591bf215546Sopenharmony_ciintel_spec_load(const struct intel_device_info *devinfo) 592bf215546Sopenharmony_ci{ 593bf215546Sopenharmony_ci struct parser_context ctx; 594bf215546Sopenharmony_ci void *buf; 595bf215546Sopenharmony_ci uint8_t *text_data = NULL; 596bf215546Sopenharmony_ci uint32_t text_offset = 0, text_length = 0; 597bf215546Sopenharmony_ci ASSERTED uint32_t total_length; 598bf215546Sopenharmony_ci uint32_t ver_10 = devinfo->verx10; 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) { 601bf215546Sopenharmony_ci if (genxml_files_table[i].ver_10 == ver_10) { 602bf215546Sopenharmony_ci text_offset = genxml_files_table[i].offset; 603bf215546Sopenharmony_ci text_length = genxml_files_table[i].length; 604bf215546Sopenharmony_ci break; 605bf215546Sopenharmony_ci } 606bf215546Sopenharmony_ci } 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci if (text_length == 0) { 609bf215546Sopenharmony_ci fprintf(stderr, "unable to find gen (%u) data\n", ver_10); 610bf215546Sopenharmony_ci return NULL; 611bf215546Sopenharmony_ci } 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci memset(&ctx, 0, sizeof ctx); 614bf215546Sopenharmony_ci ctx.parser = XML_ParserCreate(NULL); 615bf215546Sopenharmony_ci XML_SetUserData(ctx.parser, &ctx); 616bf215546Sopenharmony_ci if (ctx.parser == NULL) { 617bf215546Sopenharmony_ci fprintf(stderr, "failed to create parser\n"); 618bf215546Sopenharmony_ci return NULL; 619bf215546Sopenharmony_ci } 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci XML_SetElementHandler(ctx.parser, start_element, end_element); 622bf215546Sopenharmony_ci XML_SetCharacterDataHandler(ctx.parser, character_data); 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci ctx.spec = intel_spec_init(); 625bf215546Sopenharmony_ci if (ctx.spec == NULL) { 626bf215546Sopenharmony_ci fprintf(stderr, "Failed to create intel_spec\n"); 627bf215546Sopenharmony_ci return NULL; 628bf215546Sopenharmony_ci } 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci total_length = zlib_inflate(compress_genxmls, 631bf215546Sopenharmony_ci sizeof(compress_genxmls), 632bf215546Sopenharmony_ci (void **) &text_data); 633bf215546Sopenharmony_ci assert(text_offset + text_length <= total_length); 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci buf = XML_GetBuffer(ctx.parser, text_length); 636bf215546Sopenharmony_ci memcpy(buf, &text_data[text_offset], text_length); 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) { 639bf215546Sopenharmony_ci fprintf(stderr, 640bf215546Sopenharmony_ci "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n", 641bf215546Sopenharmony_ci XML_GetCurrentLineNumber(ctx.parser), 642bf215546Sopenharmony_ci XML_GetCurrentColumnNumber(ctx.parser), 643bf215546Sopenharmony_ci XML_GetCurrentByteIndex(ctx.parser), text_length, 644bf215546Sopenharmony_ci XML_ErrorString(XML_GetErrorCode(ctx.parser))); 645bf215546Sopenharmony_ci XML_ParserFree(ctx.parser); 646bf215546Sopenharmony_ci free(text_data); 647bf215546Sopenharmony_ci return NULL; 648bf215546Sopenharmony_ci } 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci XML_ParserFree(ctx.parser); 651bf215546Sopenharmony_ci free(text_data); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci return ctx.spec; 654bf215546Sopenharmony_ci} 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_cistruct intel_spec * 657bf215546Sopenharmony_ciintel_spec_load_filename(const char *filename) 658bf215546Sopenharmony_ci{ 659bf215546Sopenharmony_ci struct parser_context ctx; 660bf215546Sopenharmony_ci FILE *input; 661bf215546Sopenharmony_ci void *buf; 662bf215546Sopenharmony_ci size_t len; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci input = fopen(filename, "r"); 665bf215546Sopenharmony_ci if (input == NULL) { 666bf215546Sopenharmony_ci fprintf(stderr, "failed to open xml description\n"); 667bf215546Sopenharmony_ci return NULL; 668bf215546Sopenharmony_ci } 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci memset(&ctx, 0, sizeof ctx); 671bf215546Sopenharmony_ci ctx.parser = XML_ParserCreate(NULL); 672bf215546Sopenharmony_ci XML_SetUserData(ctx.parser, &ctx); 673bf215546Sopenharmony_ci if (ctx.parser == NULL) { 674bf215546Sopenharmony_ci fprintf(stderr, "failed to create parser\n"); 675bf215546Sopenharmony_ci fclose(input); 676bf215546Sopenharmony_ci return NULL; 677bf215546Sopenharmony_ci } 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci XML_SetElementHandler(ctx.parser, start_element, end_element); 680bf215546Sopenharmony_ci XML_SetCharacterDataHandler(ctx.parser, character_data); 681bf215546Sopenharmony_ci ctx.loc.filename = filename; 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci ctx.spec = intel_spec_init(); 684bf215546Sopenharmony_ci if (ctx.spec == NULL) { 685bf215546Sopenharmony_ci fprintf(stderr, "Failed to create intel_spec\n"); 686bf215546Sopenharmony_ci goto end; 687bf215546Sopenharmony_ci } 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci do { 690bf215546Sopenharmony_ci buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE); 691bf215546Sopenharmony_ci len = fread(buf, 1, XML_BUFFER_SIZE, input); 692bf215546Sopenharmony_ci if (ferror(input)) { 693bf215546Sopenharmony_ci fprintf(stderr, "fread: %m\n"); 694bf215546Sopenharmony_ci intel_spec_destroy(ctx.spec); 695bf215546Sopenharmony_ci ctx.spec = NULL; 696bf215546Sopenharmony_ci goto end; 697bf215546Sopenharmony_ci } else if (len == 0 && feof(input)) 698bf215546Sopenharmony_ci goto end; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) { 701bf215546Sopenharmony_ci fprintf(stderr, 702bf215546Sopenharmony_ci "Error parsing XML at line %ld col %ld: %s\n", 703bf215546Sopenharmony_ci XML_GetCurrentLineNumber(ctx.parser), 704bf215546Sopenharmony_ci XML_GetCurrentColumnNumber(ctx.parser), 705bf215546Sopenharmony_ci XML_ErrorString(XML_GetErrorCode(ctx.parser))); 706bf215546Sopenharmony_ci intel_spec_destroy(ctx.spec); 707bf215546Sopenharmony_ci ctx.spec = NULL; 708bf215546Sopenharmony_ci goto end; 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci } while (len > 0); 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci end: 713bf215546Sopenharmony_ci XML_ParserFree(ctx.parser); 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci fclose(input); 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci /* free ctx.spec if genxml is empty */ 718bf215546Sopenharmony_ci if (ctx.spec && 719bf215546Sopenharmony_ci _mesa_hash_table_num_entries(ctx.spec->commands) == 0 && 720bf215546Sopenharmony_ci _mesa_hash_table_num_entries(ctx.spec->structs) == 0) { 721bf215546Sopenharmony_ci fprintf(stderr, 722bf215546Sopenharmony_ci "Error parsing XML: empty spec.\n"); 723bf215546Sopenharmony_ci intel_spec_destroy(ctx.spec); 724bf215546Sopenharmony_ci return NULL; 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci return ctx.spec; 728bf215546Sopenharmony_ci} 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_cistruct intel_spec * 731bf215546Sopenharmony_ciintel_spec_load_from_path(const struct intel_device_info *devinfo, 732bf215546Sopenharmony_ci const char *path) 733bf215546Sopenharmony_ci{ 734bf215546Sopenharmony_ci size_t filename_len = strlen(path) + 20; 735bf215546Sopenharmony_ci char *filename = malloc(filename_len); 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_ci ASSERTED size_t len = snprintf(filename, filename_len, "%s/gen%i.xml", 738bf215546Sopenharmony_ci path, devinfo->ver); 739bf215546Sopenharmony_ci assert(len < filename_len); 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci struct intel_spec *spec = intel_spec_load_filename(filename); 742bf215546Sopenharmony_ci free(filename); 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci return spec; 745bf215546Sopenharmony_ci} 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_civoid intel_spec_destroy(struct intel_spec *spec) 748bf215546Sopenharmony_ci{ 749bf215546Sopenharmony_ci ralloc_free(spec); 750bf215546Sopenharmony_ci} 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_cistruct intel_group * 753bf215546Sopenharmony_ciintel_spec_find_instruction(struct intel_spec *spec, 754bf215546Sopenharmony_ci enum drm_i915_gem_engine_class engine, 755bf215546Sopenharmony_ci const uint32_t *p) 756bf215546Sopenharmony_ci{ 757bf215546Sopenharmony_ci hash_table_foreach(spec->commands, entry) { 758bf215546Sopenharmony_ci struct intel_group *command = entry->data; 759bf215546Sopenharmony_ci uint32_t opcode = *p & command->opcode_mask; 760bf215546Sopenharmony_ci if ((command->engine_mask & I915_ENGINE_CLASS_TO_MASK(engine)) && 761bf215546Sopenharmony_ci opcode == command->opcode) 762bf215546Sopenharmony_ci return command; 763bf215546Sopenharmony_ci } 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci return NULL; 766bf215546Sopenharmony_ci} 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_cistruct intel_field * 769bf215546Sopenharmony_ciintel_group_find_field(struct intel_group *group, const char *name) 770bf215546Sopenharmony_ci{ 771bf215546Sopenharmony_ci char path[256]; 772bf215546Sopenharmony_ci snprintf(path, sizeof(path), "%s/%s", group->name, name); 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci struct intel_spec *spec = group->spec; 775bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search(spec->access_cache, 776bf215546Sopenharmony_ci path); 777bf215546Sopenharmony_ci if (entry) 778bf215546Sopenharmony_ci return entry->data; 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci struct intel_field *field = group->fields; 781bf215546Sopenharmony_ci while (field) { 782bf215546Sopenharmony_ci if (strcmp(field->name, name) == 0) { 783bf215546Sopenharmony_ci _mesa_hash_table_insert(spec->access_cache, 784bf215546Sopenharmony_ci ralloc_strdup(spec, path), 785bf215546Sopenharmony_ci field); 786bf215546Sopenharmony_ci return field; 787bf215546Sopenharmony_ci } 788bf215546Sopenharmony_ci field = field->next; 789bf215546Sopenharmony_ci } 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci return NULL; 792bf215546Sopenharmony_ci} 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ciint 795bf215546Sopenharmony_ciintel_group_get_length(struct intel_group *group, const uint32_t *p) 796bf215546Sopenharmony_ci{ 797bf215546Sopenharmony_ci if (group) { 798bf215546Sopenharmony_ci if (group->fixed_length) 799bf215546Sopenharmony_ci return group->dw_length; 800bf215546Sopenharmony_ci else { 801bf215546Sopenharmony_ci struct intel_field *field = group->dword_length_field; 802bf215546Sopenharmony_ci if (field) { 803bf215546Sopenharmony_ci return field_value(p[0], field->start, field->end) + group->bias; 804bf215546Sopenharmony_ci } 805bf215546Sopenharmony_ci } 806bf215546Sopenharmony_ci } 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci uint32_t h = p[0]; 809bf215546Sopenharmony_ci uint32_t type = field_value(h, 29, 31); 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci switch (type) { 812bf215546Sopenharmony_ci case 0: /* MI */ { 813bf215546Sopenharmony_ci uint32_t opcode = field_value(h, 23, 28); 814bf215546Sopenharmony_ci if (opcode < 16) 815bf215546Sopenharmony_ci return 1; 816bf215546Sopenharmony_ci else 817bf215546Sopenharmony_ci return field_value(h, 0, 7) + 2; 818bf215546Sopenharmony_ci break; 819bf215546Sopenharmony_ci } 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_ci case 2: /* BLT */ { 822bf215546Sopenharmony_ci return field_value(h, 0, 7) + 2; 823bf215546Sopenharmony_ci } 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci case 3: /* Render */ { 826bf215546Sopenharmony_ci uint32_t subtype = field_value(h, 27, 28); 827bf215546Sopenharmony_ci uint32_t opcode = field_value(h, 24, 26); 828bf215546Sopenharmony_ci uint16_t whole_opcode = field_value(h, 16, 31); 829bf215546Sopenharmony_ci switch (subtype) { 830bf215546Sopenharmony_ci case 0: 831bf215546Sopenharmony_ci if (whole_opcode == 0x6104 /* PIPELINE_SELECT_965 */) 832bf215546Sopenharmony_ci return 1; 833bf215546Sopenharmony_ci else if (opcode < 2) 834bf215546Sopenharmony_ci return field_value(h, 0, 7) + 2; 835bf215546Sopenharmony_ci else 836bf215546Sopenharmony_ci return -1; 837bf215546Sopenharmony_ci case 1: 838bf215546Sopenharmony_ci if (opcode < 2) 839bf215546Sopenharmony_ci return 1; 840bf215546Sopenharmony_ci else 841bf215546Sopenharmony_ci return -1; 842bf215546Sopenharmony_ci case 2: { 843bf215546Sopenharmony_ci if (opcode == 0) 844bf215546Sopenharmony_ci return field_value(h, 0, 7) + 2; 845bf215546Sopenharmony_ci else if (opcode < 3) 846bf215546Sopenharmony_ci return field_value(h, 0, 15) + 2; 847bf215546Sopenharmony_ci else 848bf215546Sopenharmony_ci return -1; 849bf215546Sopenharmony_ci } 850bf215546Sopenharmony_ci case 3: 851bf215546Sopenharmony_ci if (whole_opcode == 0x780b) 852bf215546Sopenharmony_ci return 1; 853bf215546Sopenharmony_ci else if (opcode < 4) 854bf215546Sopenharmony_ci return field_value(h, 0, 7) + 2; 855bf215546Sopenharmony_ci else 856bf215546Sopenharmony_ci return -1; 857bf215546Sopenharmony_ci } 858bf215546Sopenharmony_ci } 859bf215546Sopenharmony_ci } 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci return -1; 862bf215546Sopenharmony_ci} 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_cistatic const char * 865bf215546Sopenharmony_ciintel_get_enum_name(struct intel_enum *e, uint64_t value) 866bf215546Sopenharmony_ci{ 867bf215546Sopenharmony_ci for (int i = 0; i < e->nvalues; i++) { 868bf215546Sopenharmony_ci if (e->values[i]->value == value) { 869bf215546Sopenharmony_ci return e->values[i]->name; 870bf215546Sopenharmony_ci } 871bf215546Sopenharmony_ci } 872bf215546Sopenharmony_ci return NULL; 873bf215546Sopenharmony_ci} 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_cistatic bool 876bf215546Sopenharmony_ciiter_more_fields(const struct intel_field_iterator *iter) 877bf215546Sopenharmony_ci{ 878bf215546Sopenharmony_ci return iter->field != NULL && iter->field->next != NULL; 879bf215546Sopenharmony_ci} 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_cistatic uint32_t 882bf215546Sopenharmony_ciiter_array_offset_bits(const struct intel_field_iterator *iter) 883bf215546Sopenharmony_ci{ 884bf215546Sopenharmony_ci if (iter->level == 0) 885bf215546Sopenharmony_ci return 0; 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci uint32_t offset = 0; 888bf215546Sopenharmony_ci const struct intel_group *group = iter->groups[1]; 889bf215546Sopenharmony_ci for (int level = 1; level <= iter->level; level++, group = iter->groups[level]) { 890bf215546Sopenharmony_ci uint32_t array_idx = iter->array_iter[level]; 891bf215546Sopenharmony_ci offset += group->array_offset + array_idx * group->array_item_size; 892bf215546Sopenharmony_ci } 893bf215546Sopenharmony_ci 894bf215546Sopenharmony_ci return offset; 895bf215546Sopenharmony_ci} 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci/* Checks whether we have more items in the array to iterate, or more arrays to 898bf215546Sopenharmony_ci * iterate through. 899bf215546Sopenharmony_ci */ 900bf215546Sopenharmony_ci/* descend into a non-array field */ 901bf215546Sopenharmony_cistatic void 902bf215546Sopenharmony_ciiter_push_array(struct intel_field_iterator *iter) 903bf215546Sopenharmony_ci{ 904bf215546Sopenharmony_ci assert(iter->level >= 0); 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci iter->group = iter->field->array; 907bf215546Sopenharmony_ci iter->level++; 908bf215546Sopenharmony_ci assert(iter->level < DECODE_MAX_ARRAY_DEPTH); 909bf215546Sopenharmony_ci iter->groups[iter->level] = iter->group; 910bf215546Sopenharmony_ci iter->array_iter[iter->level] = 0; 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci assert(iter->group->fields != NULL); /* an empty <group> makes no sense */ 913bf215546Sopenharmony_ci iter->field = iter->group->fields; 914bf215546Sopenharmony_ci iter->fields[iter->level] = iter->field; 915bf215546Sopenharmony_ci} 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_cistatic void 918bf215546Sopenharmony_ciiter_pop_array(struct intel_field_iterator *iter) 919bf215546Sopenharmony_ci{ 920bf215546Sopenharmony_ci assert(iter->level > 0); 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_ci iter->level--; 923bf215546Sopenharmony_ci iter->field = iter->fields[iter->level]; 924bf215546Sopenharmony_ci iter->group = iter->groups[iter->level]; 925bf215546Sopenharmony_ci} 926bf215546Sopenharmony_ci 927bf215546Sopenharmony_cistatic void 928bf215546Sopenharmony_ciiter_start_field(struct intel_field_iterator *iter, struct intel_field *field) 929bf215546Sopenharmony_ci{ 930bf215546Sopenharmony_ci iter->field = field; 931bf215546Sopenharmony_ci iter->fields[iter->level] = field; 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci while (iter->field->array) 934bf215546Sopenharmony_ci iter_push_array(iter); 935bf215546Sopenharmony_ci 936bf215546Sopenharmony_ci int array_member_offset = iter_array_offset_bits(iter); 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci iter->start_bit = array_member_offset + iter->field->start; 939bf215546Sopenharmony_ci iter->end_bit = array_member_offset + iter->field->end; 940bf215546Sopenharmony_ci iter->struct_desc = NULL; 941bf215546Sopenharmony_ci} 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_cistatic void 944bf215546Sopenharmony_ciiter_advance_array(struct intel_field_iterator *iter) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci assert(iter->level > 0); 947bf215546Sopenharmony_ci int lvl = iter->level; 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci if (iter->group->variable) 950bf215546Sopenharmony_ci iter->array_iter[lvl]++; 951bf215546Sopenharmony_ci else { 952bf215546Sopenharmony_ci if ((iter->array_iter[lvl] + 1) < iter->group->array_count) { 953bf215546Sopenharmony_ci iter->array_iter[lvl]++; 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci iter_start_field(iter, iter->group->fields); 958bf215546Sopenharmony_ci} 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_cistatic bool 961bf215546Sopenharmony_ciiter_more_array_elems(const struct intel_field_iterator *iter) 962bf215546Sopenharmony_ci{ 963bf215546Sopenharmony_ci int lvl = iter->level; 964bf215546Sopenharmony_ci assert(lvl >= 0); 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci if (iter->group->variable) { 967bf215546Sopenharmony_ci int length = intel_group_get_length(iter->group, iter->p); 968bf215546Sopenharmony_ci assert(length >= 0 && "error the length is unknown!"); 969bf215546Sopenharmony_ci return iter_array_offset_bits(iter) + iter->group->array_item_size < 970bf215546Sopenharmony_ci (length * 32); 971bf215546Sopenharmony_ci } else { 972bf215546Sopenharmony_ci return (iter->array_iter[lvl] + 1) < iter->group->array_count; 973bf215546Sopenharmony_ci } 974bf215546Sopenharmony_ci} 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_cistatic bool 977bf215546Sopenharmony_ciiter_advance_field(struct intel_field_iterator *iter) 978bf215546Sopenharmony_ci{ 979bf215546Sopenharmony_ci /* Keep looping while we either have more fields to look at, or we are 980bf215546Sopenharmony_ci * inside a <group> and can go up a level. 981bf215546Sopenharmony_ci */ 982bf215546Sopenharmony_ci while (iter_more_fields(iter) || iter->level > 0) { 983bf215546Sopenharmony_ci if (iter_more_fields(iter)) { 984bf215546Sopenharmony_ci iter_start_field(iter, iter->field->next); 985bf215546Sopenharmony_ci return true; 986bf215546Sopenharmony_ci } 987bf215546Sopenharmony_ci 988bf215546Sopenharmony_ci assert(iter->level >= 0); 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci if (iter_more_array_elems(iter)) { 991bf215546Sopenharmony_ci iter_advance_array(iter); 992bf215546Sopenharmony_ci return true; 993bf215546Sopenharmony_ci } 994bf215546Sopenharmony_ci 995bf215546Sopenharmony_ci /* At this point, we reached the end of the <group> and were on the last 996bf215546Sopenharmony_ci * iteration. So it's time to go back to the parent and then advance the 997bf215546Sopenharmony_ci * field. 998bf215546Sopenharmony_ci */ 999bf215546Sopenharmony_ci iter_pop_array(iter); 1000bf215546Sopenharmony_ci } 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_ci return false; 1003bf215546Sopenharmony_ci} 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_cistatic bool 1006bf215546Sopenharmony_ciiter_decode_field_raw(struct intel_field_iterator *iter, uint64_t *qw) 1007bf215546Sopenharmony_ci{ 1008bf215546Sopenharmony_ci *qw = 0; 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci int field_start = iter->p_bit + iter->start_bit; 1011bf215546Sopenharmony_ci int field_end = iter->p_bit + iter->end_bit; 1012bf215546Sopenharmony_ci 1013bf215546Sopenharmony_ci const uint32_t *p = iter->p + (iter->start_bit / 32); 1014bf215546Sopenharmony_ci if (iter->p_end && p >= iter->p_end) 1015bf215546Sopenharmony_ci return false; 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_ci if ((field_end - field_start) > 32) { 1018bf215546Sopenharmony_ci if (!iter->p_end || (p + 1) < iter->p_end) 1019bf215546Sopenharmony_ci *qw = ((uint64_t) p[1]) << 32; 1020bf215546Sopenharmony_ci *qw |= p[0]; 1021bf215546Sopenharmony_ci } else 1022bf215546Sopenharmony_ci *qw = p[0]; 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci *qw = field_value(*qw, field_start, field_end); 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci /* Address & offset types have to be aligned to dwords, their start bit is 1027bf215546Sopenharmony_ci * a reminder of the alignment requirement. 1028bf215546Sopenharmony_ci */ 1029bf215546Sopenharmony_ci if (iter->field->type.kind == INTEL_TYPE_ADDRESS || 1030bf215546Sopenharmony_ci iter->field->type.kind == INTEL_TYPE_OFFSET) 1031bf215546Sopenharmony_ci *qw <<= field_start % 32; 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci return true; 1034bf215546Sopenharmony_ci} 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_cistatic bool 1037bf215546Sopenharmony_ciiter_decode_field(struct intel_field_iterator *iter) 1038bf215546Sopenharmony_ci{ 1039bf215546Sopenharmony_ci union { 1040bf215546Sopenharmony_ci uint64_t qw; 1041bf215546Sopenharmony_ci float f; 1042bf215546Sopenharmony_ci } v; 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci if (iter->field->name) 1045bf215546Sopenharmony_ci snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name); 1046bf215546Sopenharmony_ci else 1047bf215546Sopenharmony_ci memset(iter->name, 0, sizeof(iter->name)); 1048bf215546Sopenharmony_ci 1049bf215546Sopenharmony_ci memset(&v, 0, sizeof(v)); 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_ci if (!iter_decode_field_raw(iter, &iter->raw_value)) 1052bf215546Sopenharmony_ci return false; 1053bf215546Sopenharmony_ci 1054bf215546Sopenharmony_ci const char *enum_name = NULL; 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci v.qw = iter->raw_value; 1057bf215546Sopenharmony_ci switch (iter->field->type.kind) { 1058bf215546Sopenharmony_ci case INTEL_TYPE_UNKNOWN: 1059bf215546Sopenharmony_ci case INTEL_TYPE_INT: { 1060bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw); 1061bf215546Sopenharmony_ci enum_name = intel_get_enum_name(&iter->field->inline_enum, v.qw); 1062bf215546Sopenharmony_ci break; 1063bf215546Sopenharmony_ci } 1064bf215546Sopenharmony_ci case INTEL_TYPE_MBZ: 1065bf215546Sopenharmony_ci case INTEL_TYPE_UINT: { 1066bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%"PRIu64, v.qw); 1067bf215546Sopenharmony_ci enum_name = intel_get_enum_name(&iter->field->inline_enum, v.qw); 1068bf215546Sopenharmony_ci break; 1069bf215546Sopenharmony_ci } 1070bf215546Sopenharmony_ci case INTEL_TYPE_BOOL: { 1071bf215546Sopenharmony_ci const char *true_string = 1072bf215546Sopenharmony_ci iter->print_colors ? "\e[0;35mtrue\e[0m" : "true"; 1073bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%s", 1074bf215546Sopenharmony_ci v.qw ? true_string : "false"); 1075bf215546Sopenharmony_ci break; 1076bf215546Sopenharmony_ci } 1077bf215546Sopenharmony_ci case INTEL_TYPE_FLOAT: 1078bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%f", v.f); 1079bf215546Sopenharmony_ci break; 1080bf215546Sopenharmony_ci case INTEL_TYPE_ADDRESS: 1081bf215546Sopenharmony_ci case INTEL_TYPE_OFFSET: 1082bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, v.qw); 1083bf215546Sopenharmony_ci break; 1084bf215546Sopenharmony_ci case INTEL_TYPE_STRUCT: 1085bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "<struct %s>", 1086bf215546Sopenharmony_ci iter->field->type.intel_struct->name); 1087bf215546Sopenharmony_ci iter->struct_desc = 1088bf215546Sopenharmony_ci intel_spec_find_struct(iter->group->spec, 1089bf215546Sopenharmony_ci iter->field->type.intel_struct->name); 1090bf215546Sopenharmony_ci break; 1091bf215546Sopenharmony_ci case INTEL_TYPE_UFIXED: 1092bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%f", 1093bf215546Sopenharmony_ci (float) v.qw / (1 << iter->field->type.f)); 1094bf215546Sopenharmony_ci break; 1095bf215546Sopenharmony_ci case INTEL_TYPE_SFIXED: { 1096bf215546Sopenharmony_ci /* Sign extend before converting */ 1097bf215546Sopenharmony_ci int bits = iter->field->type.i + iter->field->type.f + 1; 1098bf215546Sopenharmony_ci int64_t v_sign_extend = util_mask_sign_extend(v.qw, bits); 1099bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%f", 1100bf215546Sopenharmony_ci (float) v_sign_extend / (1 << iter->field->type.f)); 1101bf215546Sopenharmony_ci break; 1102bf215546Sopenharmony_ci } 1103bf215546Sopenharmony_ci case INTEL_TYPE_MBO: 1104bf215546Sopenharmony_ci break; 1105bf215546Sopenharmony_ci case INTEL_TYPE_ENUM: { 1106bf215546Sopenharmony_ci snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw); 1107bf215546Sopenharmony_ci enum_name = intel_get_enum_name(iter->field->type.intel_enum, v.qw); 1108bf215546Sopenharmony_ci break; 1109bf215546Sopenharmony_ci } 1110bf215546Sopenharmony_ci } 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci if (strlen(iter->group->name) == 0) { 1113bf215546Sopenharmony_ci int length = strlen(iter->name); 1114bf215546Sopenharmony_ci assert(iter->level >= 0); 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci int level = 1; 1117bf215546Sopenharmony_ci char *buf = iter->name + length; 1118bf215546Sopenharmony_ci while (level <= iter->level) { 1119bf215546Sopenharmony_ci int printed = snprintf(buf, sizeof(iter->name) - length, 1120bf215546Sopenharmony_ci "[%i]", iter->array_iter[level]); 1121bf215546Sopenharmony_ci level++; 1122bf215546Sopenharmony_ci length += printed; 1123bf215546Sopenharmony_ci buf += printed; 1124bf215546Sopenharmony_ci } 1125bf215546Sopenharmony_ci } 1126bf215546Sopenharmony_ci 1127bf215546Sopenharmony_ci if (enum_name) { 1128bf215546Sopenharmony_ci int length = strlen(iter->value); 1129bf215546Sopenharmony_ci snprintf(iter->value + length, sizeof(iter->value) - length, 1130bf215546Sopenharmony_ci " (%s)", enum_name); 1131bf215546Sopenharmony_ci } else if (strcmp(iter->name, "Surface Format") == 0 || 1132bf215546Sopenharmony_ci strcmp(iter->name, "Source Element Format") == 0) { 1133bf215546Sopenharmony_ci if (isl_format_is_valid((enum isl_format)v.qw)) { 1134bf215546Sopenharmony_ci const char *fmt_name = isl_format_get_name((enum isl_format)v.qw); 1135bf215546Sopenharmony_ci int length = strlen(iter->value); 1136bf215546Sopenharmony_ci snprintf(iter->value + length, sizeof(iter->value) - length, 1137bf215546Sopenharmony_ci " (%s)", fmt_name); 1138bf215546Sopenharmony_ci } 1139bf215546Sopenharmony_ci } 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci return true; 1142bf215546Sopenharmony_ci} 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_civoid 1145bf215546Sopenharmony_ciintel_field_iterator_init(struct intel_field_iterator *iter, 1146bf215546Sopenharmony_ci struct intel_group *group, 1147bf215546Sopenharmony_ci const uint32_t *p, int p_bit, 1148bf215546Sopenharmony_ci bool print_colors) 1149bf215546Sopenharmony_ci{ 1150bf215546Sopenharmony_ci memset(iter, 0, sizeof(*iter)); 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci iter->groups[iter->level] = group; 1153bf215546Sopenharmony_ci iter->group = group; 1154bf215546Sopenharmony_ci iter->p = p; 1155bf215546Sopenharmony_ci iter->p_bit = p_bit; 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci int length = intel_group_get_length(iter->group, iter->p); 1158bf215546Sopenharmony_ci assert(length >= 0 && "error the length is unknown!"); 1159bf215546Sopenharmony_ci iter->p_end = length >= 0 ? &p[length] : NULL; 1160bf215546Sopenharmony_ci iter->print_colors = print_colors; 1161bf215546Sopenharmony_ci} 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_cibool 1164bf215546Sopenharmony_ciintel_field_iterator_next(struct intel_field_iterator *iter) 1165bf215546Sopenharmony_ci{ 1166bf215546Sopenharmony_ci /* Initial condition */ 1167bf215546Sopenharmony_ci if (!iter->field) { 1168bf215546Sopenharmony_ci if (iter->group->fields) 1169bf215546Sopenharmony_ci iter_start_field(iter, iter->group->fields); 1170bf215546Sopenharmony_ci 1171bf215546Sopenharmony_ci bool result = iter_decode_field(iter); 1172bf215546Sopenharmony_ci if (!result && iter->p_end) { 1173bf215546Sopenharmony_ci /* We're dealing with a non empty struct of length=0 (BLEND_STATE on 1174bf215546Sopenharmony_ci * Gen 7.5) 1175bf215546Sopenharmony_ci */ 1176bf215546Sopenharmony_ci assert(iter->group->dw_length == 0); 1177bf215546Sopenharmony_ci } 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci return result; 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci if (!iter_advance_field(iter)) 1183bf215546Sopenharmony_ci return false; 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci if (!iter_decode_field(iter)) 1186bf215546Sopenharmony_ci return false; 1187bf215546Sopenharmony_ci 1188bf215546Sopenharmony_ci return true; 1189bf215546Sopenharmony_ci} 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_cistatic void 1192bf215546Sopenharmony_ciprint_dword_header(FILE *outfile, 1193bf215546Sopenharmony_ci struct intel_field_iterator *iter, 1194bf215546Sopenharmony_ci uint64_t offset, uint32_t dword) 1195bf215546Sopenharmony_ci{ 1196bf215546Sopenharmony_ci fprintf(outfile, "0x%08"PRIx64": 0x%08x : Dword %d\n", 1197bf215546Sopenharmony_ci offset + 4 * dword, iter->p[dword], dword); 1198bf215546Sopenharmony_ci} 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_cibool 1201bf215546Sopenharmony_ciintel_field_is_header(struct intel_field *field) 1202bf215546Sopenharmony_ci{ 1203bf215546Sopenharmony_ci uint32_t bits; 1204bf215546Sopenharmony_ci 1205bf215546Sopenharmony_ci /* Instructions are identified by the first DWord. */ 1206bf215546Sopenharmony_ci if (field->start >= 32 || 1207bf215546Sopenharmony_ci field->end >= 32) 1208bf215546Sopenharmony_ci return false; 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_ci bits = (1ULL << (field->end - field->start + 1)) - 1; 1211bf215546Sopenharmony_ci bits <<= field->start; 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci return (field->parent->opcode_mask & bits) != 0; 1214bf215546Sopenharmony_ci} 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_civoid 1217bf215546Sopenharmony_ciintel_print_group(FILE *outfile, struct intel_group *group, uint64_t offset, 1218bf215546Sopenharmony_ci const uint32_t *p, int p_bit, bool color) 1219bf215546Sopenharmony_ci{ 1220bf215546Sopenharmony_ci struct intel_field_iterator iter; 1221bf215546Sopenharmony_ci int last_dword = -1; 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci intel_field_iterator_init(&iter, group, p, p_bit, color); 1224bf215546Sopenharmony_ci while (intel_field_iterator_next(&iter)) { 1225bf215546Sopenharmony_ci int iter_dword = iter.end_bit / 32; 1226bf215546Sopenharmony_ci if (last_dword != iter_dword) { 1227bf215546Sopenharmony_ci for (int i = last_dword + 1; i <= iter_dword; i++) 1228bf215546Sopenharmony_ci print_dword_header(outfile, &iter, offset, i); 1229bf215546Sopenharmony_ci last_dword = iter_dword; 1230bf215546Sopenharmony_ci } 1231bf215546Sopenharmony_ci if (!intel_field_is_header(iter.field)) { 1232bf215546Sopenharmony_ci fprintf(outfile, " %s: %s\n", iter.name, iter.value); 1233bf215546Sopenharmony_ci if (iter.struct_desc) { 1234bf215546Sopenharmony_ci int struct_dword = iter.start_bit / 32; 1235bf215546Sopenharmony_ci uint64_t struct_offset = offset + 4 * struct_dword; 1236bf215546Sopenharmony_ci intel_print_group(outfile, iter.struct_desc, struct_offset, 1237bf215546Sopenharmony_ci &p[struct_dword], iter.start_bit % 32, color); 1238bf215546Sopenharmony_ci } 1239bf215546Sopenharmony_ci } 1240bf215546Sopenharmony_ci } 1241bf215546Sopenharmony_ci} 1242