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