panfrost: Rectify doubleplusungood extended branch
[mesa.git] / src / gallium / drivers / panfrost / midgard / disassemble.c
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 "util/half_float.h"
36
37 #define DEFINE_CASE(define, str) case define: { printf(str); break; }
38
39 static bool is_instruction_int = false;
40
41 static void
42 print_alu_opcode(midgard_alu_op op)
43 {
44 bool int_op = false;
45
46 if (alu_opcode_names[op]) {
47 printf("%s", alu_opcode_names[op]);
48
49 int_op = alu_opcode_names[op][0] == 'i';
50 } else
51 printf("alu_op_%02X", op);
52
53 /* For constant analysis */
54 is_instruction_int = int_op;
55 }
56
57 static void
58 print_ld_st_opcode(midgard_load_store_op op)
59 {
60 if (load_store_opcode_names[op])
61 printf("%s", load_store_opcode_names[op]);
62 else
63 printf("ldst_op_%02X", op);
64 }
65
66 static bool is_embedded_constant_half = false;
67 static bool is_embedded_constant_int = false;
68
69 static void
70 print_reg(unsigned reg, bool half)
71 {
72 /* Perform basic static analysis for expanding constants correctly */
73
74 if (half && (reg >> 1) == 26) {
75 is_embedded_constant_half = true;
76 is_embedded_constant_int = is_instruction_int;
77 } else if (!half && reg == 26) {
78 is_embedded_constant_int = is_instruction_int;
79 }
80
81 if (half)
82 printf("h");
83
84 printf("r%u", reg);
85 }
86
87 static char *outmod_names[4] = {
88 "",
89 ".pos",
90 "",
91 ".sat"
92 };
93
94 static void
95 print_outmod(midgard_outmod outmod)
96 {
97 printf("%s", outmod_names[outmod]);
98 }
99
100 static void
101 print_quad_word(uint32_t *words, unsigned tabs)
102 {
103 unsigned i;
104
105 for (i = 0; i < 4; i++)
106 printf("0x%08X%s ", words[i], i == 3 ? "" : ",");
107
108 printf("\n");
109 }
110
111 static void
112 print_vector_src(unsigned src_binary, bool out_high,
113 bool out_half, unsigned reg)
114 {
115 midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary;
116
117 if (src->negate)
118 printf("-");
119
120 if (src->abs)
121 printf("abs(");
122
123 //register
124
125 if (out_half) {
126 if (src->half)
127 printf(" /* half */ ");
128
129 unsigned half_reg;
130
131 if (out_high) {
132 if (src->rep_low)
133 half_reg = reg * 2;
134 else
135 half_reg = reg * 2 + 1;
136
137 if (src->rep_high)
138 printf(" /* rep_high */ ");
139 } else {
140 if (src->rep_high)
141 half_reg = reg * 2 + 1;
142 else
143 half_reg = reg * 2;
144
145 if (src->rep_low)
146 printf(" /* rep_low */ ");
147 }
148
149 print_reg(half_reg, true);
150 } else {
151 if (src->rep_high)
152 printf(" /* rep_high */ ");
153
154 if (src->half)
155 print_reg(reg * 2 + src->rep_low, true);
156 else {
157 if (src->rep_low)
158 printf(" /* rep_low */ ");
159
160 print_reg(reg, false);
161 }
162 }
163
164 //swizzle
165
166 if (src->swizzle != 0xE4) { //default swizzle
167 unsigned i;
168 static const char c[4] = "xyzw";
169
170 printf(".");
171
172 for (i = 0; i < 4; i++)
173 printf("%c", c[(src->swizzle >> (i * 2)) & 3]);
174 }
175
176 if (src->abs)
177 printf(")");
178 }
179
180 static uint16_t
181 decode_vector_imm(unsigned src2_reg, unsigned imm)
182 {
183 uint16_t ret;
184 ret = src2_reg << 11;
185 ret |= (imm & 0x7) << 8;
186 ret |= (imm >> 3) & 0xFF;
187 return ret;
188 }
189
190 static void
191 print_immediate(uint16_t imm)
192 {
193 if (is_instruction_int)
194 printf("#%d", imm);
195 else
196 printf("#%g", _mesa_half_to_float(imm));
197 }
198
199 static void
200 print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
201 unsigned tabs)
202 {
203 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
204 midgard_vector_alu *alu_field = (midgard_vector_alu *) words;
205
206 if (alu_field->reg_mode != midgard_reg_mode_half &&
207 alu_field->reg_mode != midgard_reg_mode_full) {
208 printf("unknown reg mode %u\n", alu_field->reg_mode);
209 }
210
211 /* For now, prefix instruction names with their unit, until we
212 * understand how this works on a deeper level */
213 printf("%s.", name);
214
215 print_alu_opcode(alu_field->op);
216 print_outmod(alu_field->outmod);
217 printf(" ");
218
219 bool half, out_half, out_high = false;
220 unsigned mask;
221
222 half = (alu_field->reg_mode == midgard_reg_mode_half);
223
224 if (half) {
225 if (alu_field->mask & 0xF) {
226 out_high = false;
227
228 if ((alu_field->mask & 0xF0))
229 printf("/* %X */ ", alu_field->mask);
230
231 mask = alu_field->mask;
232 } else {
233 out_high = true;
234 mask = alu_field->mask >> 4;
235 }
236 } else {
237 mask = alu_field->mask & 1;
238 mask |= (alu_field->mask & 4) >> 1;
239 mask |= (alu_field->mask & 16) >> 2;
240 mask |= (alu_field->mask & 64) >> 3;
241 }
242
243 out_half = half;
244
245 if (alu_field->dest_override != midgard_dest_override_none) {
246 if (out_half)
247 printf("/* half */ ");
248
249 out_half = true;
250
251 if (alu_field->dest_override == midgard_dest_override_lower)
252 out_high = false;
253 else if (alu_field->dest_override == midgard_dest_override_upper)
254 out_high = true;
255 else
256 assert(0);
257 }
258
259 if (out_half) {
260 if (out_high)
261 print_reg(2 * reg_info->out_reg + 1, true);
262 else
263 print_reg(2 * reg_info->out_reg, true);
264 } else
265 print_reg(reg_info->out_reg, false);
266
267 if (mask != 0xF) {
268 unsigned i;
269 static const char c[4] = "xyzw";
270
271 printf(".");
272
273 for (i = 0; i < 4; i++)
274 if (mask & (1 << i))
275 printf("%c", c[i]);
276 }
277
278 printf(", ");
279
280 print_vector_src(alu_field->src1, out_high, half, reg_info->src1_reg);
281
282 printf(", ");
283
284 if (reg_info->src2_imm) {
285 uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2);
286 print_immediate(imm);
287 } else {
288 print_vector_src(alu_field->src2, out_high, half,
289 reg_info->src2_reg);
290 }
291
292 printf("\n");
293 }
294
295 static void
296 print_scalar_src(unsigned src_binary, unsigned reg)
297 {
298 midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary;
299
300 if (src->negate)
301 printf("-");
302
303 if (src->abs)
304 printf("abs(");
305
306 if (src->full)
307 print_reg(reg, false);
308 else
309 print_reg(reg * 2 + (src->component >> 2), true);
310
311 static const char c[4] = "xyzw";
312 \
313 printf(".%c", c[src->full ? src->component >> 1 : src->component & 3]);
314
315 if (src->abs)
316 printf(")");
317
318 }
319
320 static uint16_t
321 decode_scalar_imm(unsigned src2_reg, unsigned imm)
322 {
323 uint16_t ret;
324 ret = src2_reg << 11;
325 ret |= (imm & 3) << 9;
326 ret |= (imm & 4) << 6;
327 ret |= (imm & 0x38) << 2;
328 ret |= imm >> 6;
329 return ret;
330 }
331
332 static void
333 print_scalar_field(const char *name, uint16_t *words, uint16_t reg_word,
334 unsigned tabs)
335 {
336 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
337 midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words;
338
339 if (alu_field->unknown)
340 printf("scalar ALU unknown bit set\n");
341
342 printf("%s.", name);
343 print_alu_opcode(alu_field->op);
344 print_outmod(alu_field->outmod);
345 printf(" ");
346
347 if (alu_field->output_full)
348 print_reg(reg_info->out_reg, false);
349 else
350 print_reg(reg_info->out_reg * 2 + (alu_field->output_component >> 2),
351 true);
352
353 static const char c[4] = "xyzw";
354 printf(".%c, ",
355 c[alu_field->output_full ? alu_field->output_component >> 1 :
356 alu_field->output_component & 3]);
357
358 print_scalar_src(alu_field->src1, reg_info->src1_reg);
359
360 printf(", ");
361
362 if (reg_info->src2_imm) {
363 uint16_t imm = decode_scalar_imm(reg_info->src2_reg,
364 alu_field->src2);
365 print_immediate(imm);
366 } else
367 print_scalar_src(alu_field->src2, reg_info->src2_reg);
368
369 printf("\n");
370 }
371
372 static void
373 print_branch_op(int op)
374 {
375 switch (op) {
376 case midgard_jmp_writeout_op_branch_uncond:
377 printf("uncond.");
378 break;
379
380 case midgard_jmp_writeout_op_branch_cond:
381 printf("cond.");
382 break;
383
384 case midgard_jmp_writeout_op_writeout:
385 printf("write.");
386 break;
387
388 case midgard_jmp_writeout_op_discard:
389 printf("discard.");
390 break;
391
392 default:
393 printf("unk%d.", op);
394 break;
395 }
396 }
397
398 static void
399 print_branch_cond(int cond)
400 {
401 switch (cond) {
402 case midgard_condition_write0:
403 printf("write0");
404 break;
405
406 case midgard_condition_false:
407 printf("false");
408 break;
409
410 case midgard_condition_true:
411 printf("true");
412 break;
413
414 case midgard_condition_always:
415 printf("always");
416 break;
417
418 default:
419 printf("unk%X", cond);
420 break;
421 }
422 }
423
424 static void
425 print_compact_branch_writeout_field(uint16_t word)
426 {
427 midgard_jmp_writeout_op op = word & 0x7;
428
429 switch (op) {
430 case midgard_jmp_writeout_op_branch_uncond: {
431 midgard_branch_uncond br_uncond;
432 memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond));
433 printf("br.uncond ");
434
435 if (br_uncond.unknown != 1)
436 printf("unknown:%d, ", br_uncond.unknown);
437
438 if (br_uncond.offset >= 0)
439 printf("+");
440
441 printf("%d", br_uncond.offset);
442
443 printf(" -> %X\n", br_uncond.dest_tag);
444 break;
445 }
446
447 case midgard_jmp_writeout_op_branch_cond:
448 case midgard_jmp_writeout_op_writeout:
449 case midgard_jmp_writeout_op_discard:
450 default: {
451 midgard_branch_cond br_cond;
452 memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond));
453
454 printf("br.");
455
456 print_branch_op(br_cond.op);
457 print_branch_cond(br_cond.cond);
458
459 printf(" ");
460
461 if (br_cond.offset >= 0)
462 printf("+");
463
464 printf("%d", br_cond.offset);
465
466 printf(" -> %X\n", br_cond.dest_tag);
467 break;
468 }
469 }
470 }
471
472 static void
473 print_extended_branch_writeout_field(uint8_t *words)
474 {
475 midgard_branch_extended br;
476 memcpy((char *) &br, (char *) words, sizeof(br));
477
478 printf("brx.");
479
480 print_branch_op(br.op);
481 print_branch_cond(br.cond);
482
483 if (br.unknown)
484 printf(".unknown%d", br.unknown);
485
486 printf(" ");
487
488 if (br.offset >= 0)
489 printf("+");
490
491 printf("%d", br.offset);
492
493 printf(" -> %X\n", br.dest_tag);
494 }
495
496 static unsigned
497 num_alu_fields_enabled(uint32_t control_word)
498 {
499 unsigned ret = 0;
500
501 if ((control_word >> 17) & 1)
502 ret++;
503
504 if ((control_word >> 19) & 1)
505 ret++;
506
507 if ((control_word >> 21) & 1)
508 ret++;
509
510 if ((control_word >> 23) & 1)
511 ret++;
512
513 if ((control_word >> 25) & 1)
514 ret++;
515
516 return ret;
517 }
518
519 static float
520 float_bitcast(uint32_t integer)
521 {
522 union {
523 uint32_t i;
524 float f;
525 } v;
526
527 v.i = integer;
528 return v.f;
529 }
530
531 static void
532 print_alu_word(uint32_t *words, unsigned num_quad_words,
533 unsigned tabs)
534 {
535 uint32_t control_word = words[0];
536 uint16_t *beginning_ptr = (uint16_t *)(words + 1);
537 unsigned num_fields = num_alu_fields_enabled(control_word);
538 uint16_t *word_ptr = beginning_ptr + num_fields;
539 unsigned num_words = 2 + num_fields;
540
541 if ((control_word >> 16) & 1)
542 printf("unknown bit 16 enabled\n");
543
544 if ((control_word >> 17) & 1) {
545 print_vector_field("vmul", word_ptr, *beginning_ptr, tabs);
546 beginning_ptr += 1;
547 word_ptr += 3;
548 num_words += 3;
549 }
550
551 if ((control_word >> 18) & 1)
552 printf("unknown bit 18 enabled\n");
553
554 if ((control_word >> 19) & 1) {
555 print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs);
556 beginning_ptr += 1;
557 word_ptr += 2;
558 num_words += 2;
559 }
560
561 if ((control_word >> 20) & 1)
562 printf("unknown bit 20 enabled\n");
563
564 if ((control_word >> 21) & 1) {
565 print_vector_field("vadd", word_ptr, *beginning_ptr, tabs);
566 beginning_ptr += 1;
567 word_ptr += 3;
568 num_words += 3;
569 }
570
571 if ((control_word >> 22) & 1)
572 printf("unknown bit 22 enabled\n");
573
574 if ((control_word >> 23) & 1) {
575 print_scalar_field("smul", word_ptr, *beginning_ptr, tabs);
576 beginning_ptr += 1;
577 word_ptr += 2;
578 num_words += 2;
579 }
580
581 if ((control_word >> 24) & 1)
582 printf("unknown bit 24 enabled\n");
583
584 if ((control_word >> 25) & 1) {
585 print_vector_field("lut", word_ptr, *beginning_ptr, tabs);
586 beginning_ptr += 1;
587 word_ptr += 3;
588 num_words += 3;
589 }
590
591 if ((control_word >> 26) & 1) {
592 print_compact_branch_writeout_field(*word_ptr);
593 word_ptr += 1;
594 num_words += 1;
595 }
596
597 if ((control_word >> 27) & 1) {
598 print_extended_branch_writeout_field((uint8_t *) word_ptr);
599 word_ptr += 3;
600 num_words += 3;
601 }
602
603 if (num_quad_words > (num_words + 7) / 8) {
604 assert(num_quad_words == (num_words + 15) / 8);
605 //Assume that the extra quadword is constants
606 void *consts = words + (4 * num_quad_words - 4);
607
608 if (is_embedded_constant_int) {
609 if (is_embedded_constant_half) {
610 int16_t *sconsts = (int16_t *) consts;
611 printf("sconstants %d, %d, %d, %d\n",
612 sconsts[0],
613 sconsts[1],
614 sconsts[2],
615 sconsts[3]);
616 } else {
617 int32_t *iconsts = (int32_t *) consts;
618 printf("iconstants %d, %d, %d, %d\n",
619 iconsts[0],
620 iconsts[1],
621 iconsts[2],
622 iconsts[3]);
623 }
624 } else {
625 if (is_embedded_constant_half) {
626 uint16_t *hconsts = (uint16_t *) consts;
627 printf("hconstants %g, %g, %g, %g\n",
628 _mesa_half_to_float(hconsts[0]),
629 _mesa_half_to_float(hconsts[1]),
630 _mesa_half_to_float(hconsts[2]),
631 _mesa_half_to_float(hconsts[3]));
632 } else {
633 uint32_t *fconsts = (uint32_t *) consts;
634 printf("fconstants %g, %g, %g, %g\n",
635 float_bitcast(fconsts[0]),
636 float_bitcast(fconsts[1]),
637 float_bitcast(fconsts[2]),
638 float_bitcast(fconsts[3]));
639 }
640
641 }
642 }
643 }
644
645 /* Swizzle/mask formats are common between load/store ops and texture ops, it
646 * looks like... */
647
648 static void
649 print_swizzle(uint32_t swizzle)
650 {
651 unsigned i;
652
653 if (swizzle != 0xE4) {
654 printf(".");
655
656 for (i = 0; i < 4; i++)
657 printf("%c", "xyzw"[(swizzle >> (2 * i)) & 3]);
658 }
659 }
660
661 static void
662 print_mask(uint32_t mask)
663 {
664 unsigned i;
665
666 if (mask != 0xF) {
667 printf(".");
668
669 for (i = 0; i < 4; i++)
670 if (mask & (1 << i))
671 printf("%c", "xyzw"[i]);
672
673 /* Handle degenerate case */
674 if (mask == 0)
675 printf("0");
676 }
677 }
678
679 static void
680 print_varying_parameters(midgard_load_store_word *word)
681 {
682 midgard_varying_parameter param;
683 unsigned v = word->varying_parameters;
684 memcpy(&param, &v, sizeof(param));
685
686 if (param.is_varying) {
687 /* If a varying, there are qualifiers */
688 if (param.flat)
689 printf(".flat");
690
691 if (param.interpolation != midgard_interp_default) {
692 if (param.interpolation == midgard_interp_centroid)
693 printf(".centroid");
694 else
695 printf(".interp%d", param.interpolation);
696 }
697 } else if (param.flat || param.interpolation) {
698 printf(" /* is_varying not set but varying metadata attached */");
699 }
700
701 if (param.zero1 || param.zero2)
702 printf(" /* zero tripped, %d %d */ ", param.zero1, param.zero2);
703 }
704
705 static bool
706 is_op_varying(unsigned op)
707 {
708 switch (op) {
709 case midgard_op_store_vary_16:
710 case midgard_op_store_vary_32:
711 case midgard_op_load_vary_16:
712 case midgard_op_load_vary_32:
713 return true;
714 }
715
716 return false;
717 }
718
719 static void
720 print_load_store_instr(uint64_t data,
721 unsigned tabs)
722 {
723 midgard_load_store_word *word = (midgard_load_store_word *) &data;
724
725 print_ld_st_opcode(word->op);
726
727 if (is_op_varying(word->op))
728 print_varying_parameters(word);
729
730 printf(" r%d", word->reg);
731 print_mask(word->mask);
732
733 int address = word->address;
734
735 if (word->op == midgard_op_load_uniform_32) {
736 /* Uniforms use their own addressing scheme */
737
738 int lo = word->varying_parameters >> 7;
739 int hi = word->address;
740
741 /* TODO: Combine fields logically */
742 address = (hi << 3) | lo;
743 }
744
745 printf(", %d", address);
746
747 print_swizzle(word->swizzle);
748
749 printf(", 0x%X\n", word->unknown);
750 }
751
752 static void
753 print_load_store_word(uint32_t *word, unsigned tabs)
754 {
755 midgard_load_store *load_store = (midgard_load_store *) word;
756
757 if (load_store->word1 != 3) {
758 print_load_store_instr(load_store->word1, tabs);
759 }
760
761 if (load_store->word2 != 3) {
762 print_load_store_instr(load_store->word2, tabs);
763 }
764 }
765
766 static void
767 print_texture_reg(bool full, bool select, bool upper)
768 {
769 if (full)
770 printf("r%d", REG_TEX_BASE + select);
771 else
772 printf("hr%d", (REG_TEX_BASE + select) * 2 + upper);
773
774 if (full && upper)
775 printf("// error: out full / upper mutually exclusive\n");
776
777 }
778
779 static void
780 print_texture_format(int format)
781 {
782 /* Act like a modifier */
783 printf(".");
784
785 switch (format) {
786 DEFINE_CASE(TEXTURE_2D, "2d");
787 DEFINE_CASE(TEXTURE_3D, "3d");
788
789 default:
790 printf("fmt_%d", format);
791 break;
792 }
793 }
794
795 static void
796 print_texture_op(int format)
797 {
798 /* Act like a modifier */
799 printf(".");
800
801 switch (format) {
802 DEFINE_CASE(TEXTURE_OP_NORMAL, "normal");
803 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelfetch");
804
805 default:
806 printf("op_%d", format);
807 break;
808 }
809 }
810
811 #undef DEFINE_CASE
812
813 static void
814 print_texture_word(uint32_t *word, unsigned tabs)
815 {
816 midgard_texture_word *texture = (midgard_texture_word *) word;
817
818 /* Instruction family, like ALU words have theirs */
819 printf("texture");
820
821 /* Broad category of texture operation in question */
822 print_texture_op(texture->op);
823
824 /* Specific format in question */
825 print_texture_format(texture->format);
826
827 /* Instruction "modifiers" parallel the ALU instructions. First group
828 * are modifiers that act alone */
829
830 if (!texture->filter)
831 printf(".raw");
832
833 if (texture->shadow)
834 printf(".shadow");
835
836 if (texture->cont)
837 printf(".cont");
838
839 if (texture->last)
840 printf(".last");
841
842 /* Second set are modifiers which take an extra argument each */
843
844 if (texture->has_offset)
845 printf(".offset");
846
847 if (texture->bias)
848 printf(".bias");
849
850 printf(" ");
851
852 print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper);
853 print_mask(texture->mask);
854 printf(", ");
855
856 printf("texture%d, ", texture->texture_handle);
857
858 printf("sampler%d", texture->sampler_handle);
859 print_swizzle(texture->swizzle);
860 printf(", ");
861
862 print_texture_reg(/*texture->in_reg_full*/true, texture->in_reg_select, texture->in_reg_upper);
863 printf(".%c%c, ", "xyzw"[texture->in_reg_swizzle_left],
864 "xyzw"[texture->in_reg_swizzle_right]);
865
866 /* TODO: can offsets be full words? */
867 if (texture->has_offset) {
868 print_texture_reg(false, texture->offset_reg_select, texture->offset_reg_upper);
869 printf(", ");
870 }
871
872 if (texture->bias)
873 printf("%f, ", texture->bias / 256.0f);
874
875 printf("\n");
876
877 /* While not zero in general, for these simple instructions the
878 * following unknowns are zero, so we don't include them */
879
880 if (texture->unknown1 ||
881 texture->unknown2 ||
882 texture->unknown3 ||
883 texture->unknown4 ||
884 texture->unknownA ||
885 texture->unknownB ||
886 texture->unknown8 ||
887 texture->unknown9) {
888 printf("// unknown1 = 0x%x\n", texture->unknown1);
889 printf("// unknown2 = 0x%x\n", texture->unknown2);
890 printf("// unknown3 = 0x%x\n", texture->unknown3);
891 printf("// unknown4 = 0x%x\n", texture->unknown4);
892 printf("// unknownA = 0x%x\n", texture->unknownA);
893 printf("// unknownB = 0x%x\n", texture->unknownB);
894 printf("// unknown8 = 0x%x\n", texture->unknown8);
895 printf("// unknown9 = 0x%x\n", texture->unknown9);
896 }
897
898 /* Similarly, if no offset is applied, these are zero. If an offset
899 * -is- applied, or gradients are used, etc, these are nonzero but
900 * largely unknown still. */
901
902 if (texture->offset_unknown1 ||
903 texture->offset_reg_select ||
904 texture->offset_reg_upper ||
905 texture->offset_unknown4 ||
906 texture->offset_unknown5 ||
907 texture->offset_unknown6 ||
908 texture->offset_unknown7 ||
909 texture->offset_unknown8 ||
910 texture->offset_unknown9) {
911 printf("// offset_unknown1 = 0x%x\n", texture->offset_unknown1);
912 printf("// offset_reg_select = 0x%x\n", texture->offset_reg_select);
913 printf("// offset_reg_upper = 0x%x\n", texture->offset_reg_upper);
914 printf("// offset_unknown4 = 0x%x\n", texture->offset_unknown4);
915 printf("// offset_unknown5 = 0x%x\n", texture->offset_unknown5);
916 printf("// offset_unknown6 = 0x%x\n", texture->offset_unknown6);
917 printf("// offset_unknown7 = 0x%x\n", texture->offset_unknown7);
918 printf("// offset_unknown8 = 0x%x\n", texture->offset_unknown8);
919 printf("// offset_unknown9 = 0x%x\n", texture->offset_unknown9);
920 }
921
922 /* Don't blow up */
923 if (texture->unknown7 != 0x1)
924 printf("// (!) unknown7 = %d\n", texture->unknown7);
925 }
926
927 void
928 disassemble_midgard(uint8_t *code, size_t size)
929 {
930 uint32_t *words = (uint32_t *) code;
931 unsigned num_words = size / 4;
932 int tabs = 0;
933
934 bool prefetch_flag = false;
935
936 unsigned i = 0;
937
938 while (i < num_words) {
939 unsigned num_quad_words = midgard_word_size[words[i] & 0xF];
940
941 switch (midgard_word_types[words[i] & 0xF]) {
942 case midgard_word_type_texture:
943 print_texture_word(&words[i], tabs);
944 break;
945
946 case midgard_word_type_load_store:
947 print_load_store_word(&words[i], tabs);
948 break;
949
950 case midgard_word_type_alu:
951 print_alu_word(&words[i], num_quad_words, tabs);
952
953 if (prefetch_flag)
954 return;
955
956 /* Reset word static analysis state */
957 is_embedded_constant_half = false;
958 is_embedded_constant_int = false;
959
960 break;
961
962 default:
963 printf("Unknown word type %u:\n", words[i] & 0xF);
964 num_quad_words = 1;
965 print_quad_word(&words[i], tabs);
966 printf("\n");
967 break;
968 }
969
970 printf("\n");
971
972 unsigned next = (words[i] & 0xF0) >> 4;
973
974 i += 4 * num_quad_words;
975
976 /* Break based on instruction prefetch flag */
977
978 if (i < num_words && next == 1) {
979 prefetch_flag = true;
980
981 if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu)
982 return;
983 }
984 }
985
986 return;
987 }