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