1/* Author(s): 2 * Connor Abbott 3 * Alyssa Rosenzweig 4 * 5 * Copyright (c) 2013 Connor Abbott (connor@abbott.cx) 6 * Copyright (c) 2018 Alyssa Rosenzweig (alyssa@rosenzweig.io) 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 */ 26 27#include <stdio.h> 28#include <stdint.h> 29#include <assert.h> 30#include <inttypes.h> 31#include <string.h> 32#include "midgard.h" 33#include "midgard-parse.h" 34#include "disassemble.h" 35#include "helpers.h" 36#include "util/half_float.h" 37 38#define DEFINE_CASE(define, str) case define: { printf(str); break; } 39 40static bool is_instruction_int = false; 41 42static void 43print_alu_opcode(midgard_alu_op op) 44{ 45 bool int_op = false; 46 47 if (alu_opcode_props[op].name) { 48 printf("%s", alu_opcode_props[op].name); 49 50 int_op = midgard_is_integer_op(op); 51 } else 52 printf("alu_op_%02X", op); 53 54 /* For constant analysis */ 55 is_instruction_int = int_op; 56} 57 58static void 59print_ld_st_opcode(midgard_load_store_op op) 60{ 61 if (load_store_opcode_names[op]) 62 printf("%s", load_store_opcode_names[op]); 63 else 64 printf("ldst_op_%02X", op); 65} 66 67static bool is_embedded_constant_half = false; 68static bool is_embedded_constant_int = false; 69 70static char 71prefix_for_bits(unsigned bits) 72{ 73 switch (bits) { 74 case 8: 75 return 'q'; 76 case 16: 77 return 'h'; 78 case 64: 79 return 'd'; 80 default: 81 return 0; 82 } 83} 84 85static void 86print_reg(unsigned reg, unsigned bits) 87{ 88 /* Perform basic static analysis for expanding constants correctly */ 89 90 if ((bits == 16) && (reg >> 1) == 26) { 91 is_embedded_constant_half = true; 92 is_embedded_constant_int = is_instruction_int; 93 } else if ((bits == 32) && reg == 26) { 94 is_embedded_constant_int = is_instruction_int; 95 } else if (bits == 8) { 96 /* TODO */ 97 } else if (bits == 64) { 98 /* TODO */ 99 } 100 101 char prefix = prefix_for_bits(bits); 102 103 if (prefix) 104 putchar(prefix); 105 106 printf("r%u", reg); 107} 108 109static char *outmod_names[4] = { 110 "", 111 ".pos", 112 ".int", 113 ".sat" 114}; 115 116static void 117print_outmod(midgard_outmod outmod) 118{ 119 printf("%s", outmod_names[outmod]); 120} 121 122static void 123print_quad_word(uint32_t *words, unsigned tabs) 124{ 125 unsigned i; 126 127 for (i = 0; i < 4; i++) 128 printf("0x%08X%s ", words[i], i == 3 ? "" : ","); 129 130 printf("\n"); 131} 132 133static void 134print_vector_src(unsigned src_binary, bool out_high, 135 midgard_reg_mode mode, unsigned reg, 136 bool is_int) 137{ 138 midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary; 139 140 /* Modifiers change meaning depending on the op's context */ 141 142 midgard_int_mod int_mod = src->mod; 143 144 if (is_int) { 145 switch (int_mod) { 146 case midgard_int_sign_extend: 147 printf("sext("); 148 break; 149 case midgard_int_zero_extend: 150 printf("zext("); 151 break; 152 case midgard_int_reserved: 153 printf("unk("); 154 break; 155 case midgard_int_normal: 156 /* Implicit */ 157 break; 158 } 159 } else { 160 if (src->mod & MIDGARD_FLOAT_MOD_NEG) 161 printf("-"); 162 163 if (src->mod & MIDGARD_FLOAT_MOD_ABS) 164 printf("abs("); 165 } 166 167 //register 168 169 if (mode == midgard_reg_mode_8) { 170 if (src->half) 171 printf(" /* half */ "); 172 173 unsigned quarter_reg = reg * 2; 174 175 if (out_high) { 176 if (!src->rep_low) 177 quarter_reg++; 178 179 if (src->rep_high) 180 printf(" /* rep_high */ "); 181 } else { 182 if (src->rep_high) 183 quarter_reg++; 184 185 if (src->rep_low) 186 printf(" /* rep_low */ "); 187 } 188 189 print_reg(quarter_reg, 8); 190 } else if (mode == midgard_reg_mode_16) { 191 if (src->half) 192 printf(" /* half */ "); 193 194 unsigned half_reg = reg * 2; 195 196 if (out_high) { 197 if (!src->rep_low) 198 half_reg++; 199 200 if (src->rep_high) 201 printf(" /* rep_high */ "); 202 } else { 203 if (src->rep_high) 204 half_reg++; 205 206 if (src->rep_low) 207 printf(" /* rep_low */ "); 208 } 209 210 print_reg(half_reg, 16); 211 } else if (mode == midgard_reg_mode_32) { 212 if (src->rep_high) 213 printf(" /* rep_high */ "); 214 215 if (src->half) 216 print_reg(reg * 2 + src->rep_low, 16); 217 else { 218 if (src->rep_low) 219 printf(" /* rep_low */ "); 220 221 print_reg(reg, 32); 222 } 223 } else if (mode == midgard_reg_mode_64) { 224 if (src->rep_high) 225 printf(" /* rep_high */ "); 226 227 if (src->rep_low) 228 printf(" /* rep_low */ "); 229 230 if (src->half) 231 printf(" /* half */ "); 232 233 if (out_high) 234 printf(" /* out_high */ "); 235 236 print_reg(reg, 64); 237 } 238 239 //swizzle 240 241 if (src->swizzle != 0xE4) { //default swizzle 242 unsigned i; 243 static const char c[4] = "xyzw"; 244 245 printf("."); 246 247 for (i = 0; i < 4; i++) 248 printf("%c", c[(src->swizzle >> (i * 2)) & 3]); 249 } 250 251 /* Since we wrapped with a function-looking thing */ 252 253 if ((is_int && (int_mod != midgard_int_normal)) 254 || (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS)) 255 printf(")"); 256} 257 258static uint16_t 259decode_vector_imm(unsigned src2_reg, unsigned imm) 260{ 261 uint16_t ret; 262 ret = src2_reg << 11; 263 ret |= (imm & 0x7) << 8; 264 ret |= (imm >> 3) & 0xFF; 265 return ret; 266} 267 268static void 269print_immediate(uint16_t imm) 270{ 271 if (is_instruction_int) 272 printf("#%d", imm); 273 else 274 printf("#%g", _mesa_half_to_float(imm)); 275} 276 277static int 278bits_for_mode(midgard_reg_mode mode) 279{ 280 switch (mode) { 281 case midgard_reg_mode_8: 282 return 8; 283 case midgard_reg_mode_16: 284 return 16; 285 case midgard_reg_mode_32: 286 return 32; 287 case midgard_reg_mode_64: 288 return 64; 289 default: 290 return 0; 291 } 292} 293 294static void 295print_dest(unsigned reg, midgard_reg_mode mode, midgard_dest_override override, bool out_high) 296{ 297 bool overriden = override != midgard_dest_override_none; 298 bool overriden_up = override == midgard_dest_override_upper; 299 300 /* Depending on the mode and override, we determine the type of 301 * destination addressed. Absent an override, we address just the 302 * type of the operation itself, directly at the out_reg register 303 * (scaled if necessary to disambiguate, raised if necessary) */ 304 305 unsigned bits = bits_for_mode(mode); 306 307 if (overriden) 308 bits /= 2; 309 310 /* Sanity check the override */ 311 312 if (overriden) { 313 bool modeable = (mode == midgard_reg_mode_32) || (mode == midgard_reg_mode_16); 314 bool known = override != 0x3; /* Unused value */ 315 bool uppable = !overriden_up || (mode == midgard_reg_mode_32); 316 317 if (!(modeable && known && uppable)) 318 printf("/* do%d */ ", override); 319 } 320 321 switch (mode) { 322 case midgard_reg_mode_8: 323 case midgard_reg_mode_16: 324 reg = reg * 2 + out_high; 325 break; 326 327 case midgard_reg_mode_32: 328 if (overriden) { 329 reg = (reg * 2) + overriden_up; 330 } 331 332 break; 333 334 default: 335 break; 336 } 337 338 print_reg(reg, bits); 339} 340 341static void 342print_vector_field(const char *name, uint16_t *words, uint16_t reg_word, 343 unsigned tabs) 344{ 345 midgard_reg_info *reg_info = (midgard_reg_info *)®_word; 346 midgard_vector_alu *alu_field = (midgard_vector_alu *) words; 347 midgard_reg_mode mode = alu_field->reg_mode; 348 349 /* For now, prefix instruction names with their unit, until we 350 * understand how this works on a deeper level */ 351 printf("%s.", name); 352 353 print_alu_opcode(alu_field->op); 354 print_outmod(alu_field->outmod); 355 printf(" "); 356 357 bool out_high = false; 358 unsigned mask; 359 360 if (mode == midgard_reg_mode_16 361 || mode == midgard_reg_mode_8) { 362 363 /* For partial views, the mask denotes which adjacent register 364 * is used as the window into the larger register */ 365 366 if (alu_field->mask & 0xF) { 367 out_high = false; 368 369 if ((alu_field->mask & 0xF0)) 370 printf("/* %X */ ", alu_field->mask); 371 372 mask = alu_field->mask; 373 } else { 374 out_high = true; 375 mask = alu_field->mask >> 4; 376 } 377 } else { 378 /* For full 32-bit, every other bit is duplicated, so we only 379 * pick every other to find the effective mask */ 380 381 mask = alu_field->mask & 1; 382 mask |= (alu_field->mask & 4) >> 1; 383 mask |= (alu_field->mask & 16) >> 2; 384 mask |= (alu_field->mask & 64) >> 3; 385 386 /* ... but verify! */ 387 388 unsigned checked = alu_field->mask & 0x55; 389 unsigned opposite = alu_field->mask & 0xAA; 390 391 if ((checked << 1) != opposite) 392 printf("/* %X */ ", alu_field->mask); 393 } 394 395 /* First, print the destination */ 396 print_dest(reg_info->out_reg, mode, alu_field->dest_override, out_high); 397 398 /* The semantics here are not totally grokked yet */ 399 if (alu_field->dest_override == midgard_dest_override_upper) 400 out_high = true; 401 402 if (mask != 0xF) { 403 unsigned i; 404 static const char c[4] = "xyzw"; 405 406 printf("."); 407 408 for (i = 0; i < 4; i++) 409 if (mask & (1 << i)) 410 printf("%c", c[i]); 411 } 412 413 printf(", "); 414 415 bool is_int = midgard_is_integer_op(alu_field->op); 416 print_vector_src(alu_field->src1, out_high, mode, reg_info->src1_reg, is_int); 417 418 printf(", "); 419 420 if (reg_info->src2_imm) { 421 uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2); 422 print_immediate(imm); 423 } else { 424 print_vector_src(alu_field->src2, out_high, mode, 425 reg_info->src2_reg, is_int); 426 } 427 428 printf("\n"); 429} 430 431static void 432print_scalar_src(unsigned src_binary, unsigned reg) 433{ 434 midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary; 435 436 if (src->negate) 437 printf("-"); 438 439 if (src->abs) 440 printf("abs("); 441 442 if (src->full) 443 print_reg(reg, 32); 444 else 445 print_reg(reg * 2 + (src->component >> 2), 16); 446 447 static const char c[4] = "xyzw"; 448 \ 449 printf(".%c", c[src->full ? src->component >> 1 : src->component & 3]); 450 451 if (src->abs) 452 printf(")"); 453 454} 455 456static uint16_t 457decode_scalar_imm(unsigned src2_reg, unsigned imm) 458{ 459 uint16_t ret; 460 ret = src2_reg << 11; 461 ret |= (imm & 3) << 9; 462 ret |= (imm & 4) << 6; 463 ret |= (imm & 0x38) << 2; 464 ret |= imm >> 6; 465 return ret; 466} 467 468static void 469print_scalar_field(const char *name, uint16_t *words, uint16_t reg_word, 470 unsigned tabs) 471{ 472 midgard_reg_info *reg_info = (midgard_reg_info *)®_word; 473 midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words; 474 475 if (alu_field->unknown) 476 printf("scalar ALU unknown bit set\n"); 477 478 printf("%s.", name); 479 print_alu_opcode(alu_field->op); 480 print_outmod(alu_field->outmod); 481 printf(" "); 482 483 if (alu_field->output_full) 484 print_reg(reg_info->out_reg, 32); 485 else 486 print_reg(reg_info->out_reg * 2 + (alu_field->output_component >> 2), 487 16); 488 489 static const char c[4] = "xyzw"; 490 printf(".%c, ", 491 c[alu_field->output_full ? alu_field->output_component >> 1 : 492 alu_field->output_component & 3]); 493 494 print_scalar_src(alu_field->src1, reg_info->src1_reg); 495 496 printf(", "); 497 498 if (reg_info->src2_imm) { 499 uint16_t imm = decode_scalar_imm(reg_info->src2_reg, 500 alu_field->src2); 501 print_immediate(imm); 502 } else 503 print_scalar_src(alu_field->src2, reg_info->src2_reg); 504 505 printf("\n"); 506} 507 508static void 509print_branch_op(int op) 510{ 511 switch (op) { 512 case midgard_jmp_writeout_op_branch_uncond: 513 printf("uncond."); 514 break; 515 516 case midgard_jmp_writeout_op_branch_cond: 517 printf("cond."); 518 break; 519 520 case midgard_jmp_writeout_op_writeout: 521 printf("write."); 522 break; 523 524 case midgard_jmp_writeout_op_tilebuffer_pending: 525 printf("tilebuffer."); 526 break; 527 528 case midgard_jmp_writeout_op_discard: 529 printf("discard."); 530 break; 531 532 default: 533 printf("unk%d.", op); 534 break; 535 } 536} 537 538static void 539print_branch_cond(int cond) 540{ 541 switch (cond) { 542 case midgard_condition_write0: 543 printf("write0"); 544 break; 545 546 case midgard_condition_false: 547 printf("false"); 548 break; 549 550 case midgard_condition_true: 551 printf("true"); 552 break; 553 554 case midgard_condition_always: 555 printf("always"); 556 break; 557 558 default: 559 printf("unk%X", cond); 560 break; 561 } 562} 563 564static void 565print_compact_branch_writeout_field(uint16_t word) 566{ 567 midgard_jmp_writeout_op op = word & 0x7; 568 569 switch (op) { 570 case midgard_jmp_writeout_op_branch_uncond: { 571 midgard_branch_uncond br_uncond; 572 memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond)); 573 printf("br.uncond "); 574 575 if (br_uncond.unknown != 1) 576 printf("unknown:%d, ", br_uncond.unknown); 577 578 if (br_uncond.offset >= 0) 579 printf("+"); 580 581 printf("%d", br_uncond.offset); 582 583 printf(" -> %X\n", br_uncond.dest_tag); 584 break; 585 } 586 587 case midgard_jmp_writeout_op_branch_cond: 588 case midgard_jmp_writeout_op_writeout: 589 case midgard_jmp_writeout_op_discard: 590 default: { 591 midgard_branch_cond br_cond; 592 memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond)); 593 594 printf("br."); 595 596 print_branch_op(br_cond.op); 597 print_branch_cond(br_cond.cond); 598 599 printf(" "); 600 601 if (br_cond.offset >= 0) 602 printf("+"); 603 604 printf("%d", br_cond.offset); 605 606 printf(" -> %X\n", br_cond.dest_tag); 607 break; 608 } 609 } 610} 611 612static void 613print_extended_branch_writeout_field(uint8_t *words) 614{ 615 midgard_branch_extended br; 616 memcpy((char *) &br, (char *) words, sizeof(br)); 617 618 printf("brx."); 619 620 print_branch_op(br.op); 621 622 /* Condition repeated 8 times in all known cases. Check this. */ 623 624 unsigned cond = br.cond & 0x3; 625 626 for (unsigned i = 0; i < 16; i += 2) { 627 assert(((br.cond >> i) & 0x3) == cond); 628 } 629 630 print_branch_cond(cond); 631 632 if (br.unknown) 633 printf(".unknown%d", br.unknown); 634 635 printf(" "); 636 637 if (br.offset >= 0) 638 printf("+"); 639 640 printf("%d", br.offset); 641 642 printf(" -> %X\n", br.dest_tag); 643} 644 645static unsigned 646num_alu_fields_enabled(uint32_t control_word) 647{ 648 unsigned ret = 0; 649 650 if ((control_word >> 17) & 1) 651 ret++; 652 653 if ((control_word >> 19) & 1) 654 ret++; 655 656 if ((control_word >> 21) & 1) 657 ret++; 658 659 if ((control_word >> 23) & 1) 660 ret++; 661 662 if ((control_word >> 25) & 1) 663 ret++; 664 665 return ret; 666} 667 668static float 669float_bitcast(uint32_t integer) 670{ 671 union { 672 uint32_t i; 673 float f; 674 } v; 675 676 v.i = integer; 677 return v.f; 678} 679 680static void 681print_alu_word(uint32_t *words, unsigned num_quad_words, 682 unsigned tabs) 683{ 684 uint32_t control_word = words[0]; 685 uint16_t *beginning_ptr = (uint16_t *)(words + 1); 686 unsigned num_fields = num_alu_fields_enabled(control_word); 687 uint16_t *word_ptr = beginning_ptr + num_fields; 688 unsigned num_words = 2 + num_fields; 689 690 if ((control_word >> 16) & 1) 691 printf("unknown bit 16 enabled\n"); 692 693 if ((control_word >> 17) & 1) { 694 print_vector_field("vmul", word_ptr, *beginning_ptr, tabs); 695 beginning_ptr += 1; 696 word_ptr += 3; 697 num_words += 3; 698 } 699 700 if ((control_word >> 18) & 1) 701 printf("unknown bit 18 enabled\n"); 702 703 if ((control_word >> 19) & 1) { 704 print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs); 705 beginning_ptr += 1; 706 word_ptr += 2; 707 num_words += 2; 708 } 709 710 if ((control_word >> 20) & 1) 711 printf("unknown bit 20 enabled\n"); 712 713 if ((control_word >> 21) & 1) { 714 print_vector_field("vadd", word_ptr, *beginning_ptr, tabs); 715 beginning_ptr += 1; 716 word_ptr += 3; 717 num_words += 3; 718 } 719 720 if ((control_word >> 22) & 1) 721 printf("unknown bit 22 enabled\n"); 722 723 if ((control_word >> 23) & 1) { 724 print_scalar_field("smul", word_ptr, *beginning_ptr, tabs); 725 beginning_ptr += 1; 726 word_ptr += 2; 727 num_words += 2; 728 } 729 730 if ((control_word >> 24) & 1) 731 printf("unknown bit 24 enabled\n"); 732 733 if ((control_word >> 25) & 1) { 734 print_vector_field("lut", word_ptr, *beginning_ptr, tabs); 735 beginning_ptr += 1; 736 word_ptr += 3; 737 num_words += 3; 738 } 739 740 if ((control_word >> 26) & 1) { 741 print_compact_branch_writeout_field(*word_ptr); 742 word_ptr += 1; 743 num_words += 1; 744 } 745 746 if ((control_word >> 27) & 1) { 747 print_extended_branch_writeout_field((uint8_t *) word_ptr); 748 word_ptr += 3; 749 num_words += 3; 750 } 751 752 if (num_quad_words > (num_words + 7) / 8) { 753 assert(num_quad_words == (num_words + 15) / 8); 754 //Assume that the extra quadword is constants 755 void *consts = words + (4 * num_quad_words - 4); 756 757 if (is_embedded_constant_int) { 758 if (is_embedded_constant_half) { 759 int16_t *sconsts = (int16_t *) consts; 760 printf("sconstants %d, %d, %d, %d\n", 761 sconsts[0], 762 sconsts[1], 763 sconsts[2], 764 sconsts[3]); 765 } else { 766 int32_t *iconsts = (int32_t *) consts; 767 printf("iconstants %d, %d, %d, %d\n", 768 iconsts[0], 769 iconsts[1], 770 iconsts[2], 771 iconsts[3]); 772 } 773 } else { 774 if (is_embedded_constant_half) { 775 uint16_t *hconsts = (uint16_t *) consts; 776 printf("hconstants %g, %g, %g, %g\n", 777 _mesa_half_to_float(hconsts[0]), 778 _mesa_half_to_float(hconsts[1]), 779 _mesa_half_to_float(hconsts[2]), 780 _mesa_half_to_float(hconsts[3])); 781 } else { 782 uint32_t *fconsts = (uint32_t *) consts; 783 printf("fconstants %g, %g, %g, %g\n", 784 float_bitcast(fconsts[0]), 785 float_bitcast(fconsts[1]), 786 float_bitcast(fconsts[2]), 787 float_bitcast(fconsts[3])); 788 } 789 790 } 791 } 792} 793 794/* Swizzle/mask formats are common between load/store ops and texture ops, it 795 * looks like... */ 796 797static void 798print_swizzle(uint32_t swizzle) 799{ 800 unsigned i; 801 802 if (swizzle != 0xE4) { 803 printf("."); 804 805 for (i = 0; i < 4; i++) 806 printf("%c", "xyzw"[(swizzle >> (2 * i)) & 3]); 807 } 808} 809 810static void 811print_mask(uint32_t mask) 812{ 813 unsigned i; 814 815 if (mask != 0xF) { 816 printf("."); 817 818 for (i = 0; i < 4; i++) 819 if (mask & (1 << i)) 820 printf("%c", "xyzw"[i]); 821 822 /* Handle degenerate case */ 823 if (mask == 0) 824 printf("0"); 825 } 826} 827 828static void 829print_varying_parameters(midgard_load_store_word *word) 830{ 831 midgard_varying_parameter param; 832 unsigned v = word->varying_parameters; 833 memcpy(¶m, &v, sizeof(param)); 834 835 if (param.is_varying) { 836 /* If a varying, there are qualifiers */ 837 if (param.flat) 838 printf(".flat"); 839 840 if (param.interpolation != midgard_interp_default) { 841 if (param.interpolation == midgard_interp_centroid) 842 printf(".centroid"); 843 else 844 printf(".interp%d", param.interpolation); 845 } 846 } else if (param.flat || param.interpolation) { 847 printf(" /* is_varying not set but varying metadata attached */"); 848 } 849 850 if (param.zero1 || param.zero2) 851 printf(" /* zero tripped, %d %d */ ", param.zero1, param.zero2); 852} 853 854static bool 855is_op_varying(unsigned op) 856{ 857 switch (op) { 858 case midgard_op_store_vary_16: 859 case midgard_op_store_vary_32: 860 case midgard_op_load_vary_16: 861 case midgard_op_load_vary_32: 862 return true; 863 } 864 865 return false; 866} 867 868static void 869print_load_store_instr(uint64_t data, 870 unsigned tabs) 871{ 872 midgard_load_store_word *word = (midgard_load_store_word *) &data; 873 874 print_ld_st_opcode(word->op); 875 876 if (is_op_varying(word->op)) 877 print_varying_parameters(word); 878 879 printf(" r%d", word->reg); 880 print_mask(word->mask); 881 882 int address = word->address; 883 884 if (word->op == midgard_op_load_uniform_32) { 885 /* Uniforms use their own addressing scheme */ 886 887 int lo = word->varying_parameters >> 7; 888 int hi = word->address; 889 890 /* TODO: Combine fields logically */ 891 address = (hi << 3) | lo; 892 } 893 894 printf(", %d", address); 895 896 print_swizzle(word->swizzle); 897 898 printf(", 0x%X /* %X */\n", word->unknown, word->varying_parameters); 899} 900 901static void 902print_load_store_word(uint32_t *word, unsigned tabs) 903{ 904 midgard_load_store *load_store = (midgard_load_store *) word; 905 906 if (load_store->word1 != 3) { 907 print_load_store_instr(load_store->word1, tabs); 908 } 909 910 if (load_store->word2 != 3) { 911 print_load_store_instr(load_store->word2, tabs); 912 } 913} 914 915static void 916print_texture_reg(bool full, bool select, bool upper) 917{ 918 if (full) 919 printf("r%d", REG_TEX_BASE + select); 920 else 921 printf("hr%d", (REG_TEX_BASE + select) * 2 + upper); 922 923 if (full && upper) 924 printf("// error: out full / upper mutually exclusive\n"); 925 926} 927 928static void 929print_texture_format(int format) 930{ 931 /* Act like a modifier */ 932 printf("."); 933 934 switch (format) { 935 DEFINE_CASE(TEXTURE_2D, "2d"); 936 DEFINE_CASE(TEXTURE_3D, "3d"); 937 DEFINE_CASE(TEXTURE_CUBE, "cube"); 938 939 default: 940 printf("fmt_%d", format); 941 break; 942 } 943} 944 945static void 946print_texture_op(int format) 947{ 948 /* Act like a modifier */ 949 printf("."); 950 951 switch (format) { 952 DEFINE_CASE(TEXTURE_OP_NORMAL, "normal"); 953 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelfetch"); 954 955 default: 956 printf("op_%d", format); 957 break; 958 } 959} 960 961#undef DEFINE_CASE 962 963static void 964print_texture_word(uint32_t *word, unsigned tabs) 965{ 966 midgard_texture_word *texture = (midgard_texture_word *) word; 967 968 /* Instruction family, like ALU words have theirs */ 969 printf("texture"); 970 971 /* Broad category of texture operation in question */ 972 print_texture_op(texture->op); 973 974 /* Specific format in question */ 975 print_texture_format(texture->format); 976 977 /* Instruction "modifiers" parallel the ALU instructions. First group 978 * are modifiers that act alone */ 979 980 if (!texture->filter) 981 printf(".raw"); 982 983 if (texture->shadow) 984 printf(".shadow"); 985 986 if (texture->cont) 987 printf(".cont"); 988 989 if (texture->last) 990 printf(".last"); 991 992 /* Second set are modifiers which take an extra argument each */ 993 994 if (texture->has_offset) 995 printf(".offset"); 996 997 if (texture->bias) 998 printf(".bias"); 999 1000 printf(" "); 1001 1002 print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper); 1003 print_mask(texture->mask); 1004 printf(", "); 1005 1006 printf("texture%d, ", texture->texture_handle); 1007 1008 printf("sampler%d", texture->sampler_handle); 1009 print_swizzle(texture->swizzle); 1010 printf(", "); 1011 1012 print_texture_reg(/*texture->in_reg_full*/true, texture->in_reg_select, texture->in_reg_upper); 1013 printf(".%c%c, ", "xyzw"[texture->in_reg_swizzle_left], 1014 "xyzw"[texture->in_reg_swizzle_right]); 1015 1016 /* TODO: can offsets be full words? */ 1017 if (texture->has_offset) { 1018 print_texture_reg(false, texture->offset_reg_select, texture->offset_reg_upper); 1019 printf(", "); 1020 } 1021 1022 if (texture->bias) 1023 printf("%f, ", texture->bias / 256.0f); 1024 1025 printf("\n"); 1026 1027 /* While not zero in general, for these simple instructions the 1028 * following unknowns are zero, so we don't include them */ 1029 1030 if (texture->unknown1 || 1031 texture->unknown2 || 1032 texture->unknown3 || 1033 texture->unknown4 || 1034 texture->unknownA || 1035 texture->unknownB || 1036 texture->unknown8 || 1037 texture->unknown9) { 1038 printf("// unknown1 = 0x%x\n", texture->unknown1); 1039 printf("// unknown2 = 0x%x\n", texture->unknown2); 1040 printf("// unknown3 = 0x%x\n", texture->unknown3); 1041 printf("// unknown4 = 0x%x\n", texture->unknown4); 1042 printf("// unknownA = 0x%x\n", texture->unknownA); 1043 printf("// unknownB = 0x%x\n", texture->unknownB); 1044 printf("// unknown8 = 0x%x\n", texture->unknown8); 1045 printf("// unknown9 = 0x%x\n", texture->unknown9); 1046 } 1047 1048 /* Similarly, if no offset is applied, these are zero. If an offset 1049 * -is- applied, or gradients are used, etc, these are nonzero but 1050 * largely unknown still. */ 1051 1052 if (texture->offset_unknown1 || 1053 texture->offset_reg_select || 1054 texture->offset_reg_upper || 1055 texture->offset_unknown4 || 1056 texture->offset_unknown5 || 1057 texture->offset_unknown6 || 1058 texture->offset_unknown7 || 1059 texture->offset_unknown8 || 1060 texture->offset_unknown9) { 1061 printf("// offset_unknown1 = 0x%x\n", texture->offset_unknown1); 1062 printf("// offset_reg_select = 0x%x\n", texture->offset_reg_select); 1063 printf("// offset_reg_upper = 0x%x\n", texture->offset_reg_upper); 1064 printf("// offset_unknown4 = 0x%x\n", texture->offset_unknown4); 1065 printf("// offset_unknown5 = 0x%x\n", texture->offset_unknown5); 1066 printf("// offset_unknown6 = 0x%x\n", texture->offset_unknown6); 1067 printf("// offset_unknown7 = 0x%x\n", texture->offset_unknown7); 1068 printf("// offset_unknown8 = 0x%x\n", texture->offset_unknown8); 1069 printf("// offset_unknown9 = 0x%x\n", texture->offset_unknown9); 1070 } 1071 1072 /* Don't blow up */ 1073 if (texture->unknown7 != 0x1) 1074 printf("// (!) unknown7 = %d\n", texture->unknown7); 1075} 1076 1077void 1078disassemble_midgard(uint8_t *code, size_t size) 1079{ 1080 uint32_t *words = (uint32_t *) code; 1081 unsigned num_words = size / 4; 1082 int tabs = 0; 1083 1084 bool prefetch_flag = false; 1085 1086 unsigned i = 0; 1087 1088 while (i < num_words) { 1089 unsigned num_quad_words = midgard_word_size[words[i] & 0xF]; 1090 1091 switch (midgard_word_types[words[i] & 0xF]) { 1092 case midgard_word_type_texture: 1093 print_texture_word(&words[i], tabs); 1094 break; 1095 1096 case midgard_word_type_load_store: 1097 print_load_store_word(&words[i], tabs); 1098 break; 1099 1100 case midgard_word_type_alu: 1101 print_alu_word(&words[i], num_quad_words, tabs); 1102 1103 if (prefetch_flag) 1104 return; 1105 1106 /* Reset word static analysis state */ 1107 is_embedded_constant_half = false; 1108 is_embedded_constant_int = false; 1109 1110 break; 1111 1112 default: 1113 printf("Unknown word type %u:\n", words[i] & 0xF); 1114 num_quad_words = 1; 1115 print_quad_word(&words[i], tabs); 1116 printf("\n"); 1117 break; 1118 } 1119 1120 printf("\n"); 1121 1122 unsigned next = (words[i] & 0xF0) >> 4; 1123 1124 i += 4 * num_quad_words; 1125 1126 /* Break based on instruction prefetch flag */ 1127 1128 if (i < num_words && next == 1) { 1129 prefetch_flag = true; 1130 1131 if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu) 1132 return; 1133 } 1134 } 1135 1136 return; 1137} 1138