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