panfrost: Preserve w sign in perspective division
[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_cond:
377 printf("cond.");
378 break;
379
380 case midgard_jmp_writeout_op_writeout:
381 printf("write.");
382 break;
383
384 case midgard_jmp_writeout_op_discard:
385 printf("discard.");
386 break;
387
388 default:
389 printf("unk%d.", op);
390 break;
391 }
392 }
393
394 static void
395 print_branch_cond(int cond)
396 {
397 switch (cond) {
398 case midgard_condition_write0:
399 printf("write0");
400 break;
401
402 case midgard_condition_false:
403 printf("false");
404 break;
405
406 case midgard_condition_true:
407 printf("true");
408 break;
409
410 case midgard_condition_always:
411 printf("always");
412 break;
413
414 default:
415 break;
416 }
417 }
418
419 static void
420 print_compact_branch_writeout_field(uint16_t word)
421 {
422 midgard_jmp_writeout_op op = word & 0x7;
423
424 switch (op) {
425 case midgard_jmp_writeout_op_branch_uncond: {
426 midgard_branch_uncond br_uncond;
427 memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond));
428 printf("br.uncond ");
429
430 if (br_uncond.unknown != 1)
431 printf("unknown:%d, ", br_uncond.unknown);
432
433 if (br_uncond.offset >= 0)
434 printf("+");
435
436 printf("%d", br_uncond.offset);
437
438 printf(" -> %X\n", br_uncond.dest_tag);
439 break;
440 }
441
442 case midgard_jmp_writeout_op_branch_cond:
443 case midgard_jmp_writeout_op_writeout:
444 case midgard_jmp_writeout_op_discard:
445 default: {
446 midgard_branch_cond br_cond;
447 memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond));
448
449 printf("br.");
450
451 print_branch_op(br_cond.op);
452 print_branch_cond(br_cond.cond);
453
454 printf(" ");
455
456 if (br_cond.offset >= 0)
457 printf("+");
458
459 printf("%d", br_cond.offset);
460
461 printf(" -> %X\n", br_cond.dest_tag);
462 break;
463 }
464 }
465 }
466
467 static void
468 print_extended_branch_writeout_field(uint8_t *words)
469 {
470 midgard_branch_extended br;
471 memcpy((char *) &br, (char *) words, sizeof(br));
472
473 printf("br.");
474
475 print_branch_op(br.op);
476 print_branch_cond(br.cond);
477
478 /* XXX: This can't be right */
479 if (br.unknown)
480 printf(".unknown%d\n", br.unknown);
481
482 if (br.zero)
483 printf(".zero%d\n", br.zero);
484
485 printf(" ");
486
487 if (br.offset >= 0)
488 printf("+");
489
490 printf("%d", br.offset);
491
492 printf(" -> %X\n", br.dest_tag);
493 }
494
495 static unsigned
496 num_alu_fields_enabled(uint32_t control_word)
497 {
498 unsigned ret = 0;
499
500 if ((control_word >> 17) & 1)
501 ret++;
502
503 if ((control_word >> 19) & 1)
504 ret++;
505
506 if ((control_word >> 21) & 1)
507 ret++;
508
509 if ((control_word >> 23) & 1)
510 ret++;
511
512 if ((control_word >> 25) & 1)
513 ret++;
514
515 return ret;
516 }
517
518 static float
519 float_bitcast(uint32_t integer)
520 {
521 union {
522 uint32_t i;
523 float f;
524 } v;
525
526 v.i = integer;
527 return v.f;
528 }
529
530 static void
531 print_alu_word(uint32_t *words, unsigned num_quad_words,
532 unsigned tabs)
533 {
534 uint32_t control_word = words[0];
535 uint16_t *beginning_ptr = (uint16_t *)(words + 1);
536 unsigned num_fields = num_alu_fields_enabled(control_word);
537 uint16_t *word_ptr = beginning_ptr + num_fields;
538 unsigned num_words = 2 + num_fields;
539
540 if ((control_word >> 16) & 1)
541 printf("unknown bit 16 enabled\n");
542
543 if ((control_word >> 17) & 1) {
544 print_vector_field("vmul", word_ptr, *beginning_ptr, tabs);
545 beginning_ptr += 1;
546 word_ptr += 3;
547 num_words += 3;
548 }
549
550 if ((control_word >> 18) & 1)
551 printf("unknown bit 18 enabled\n");
552
553 if ((control_word >> 19) & 1) {
554 print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs);
555 beginning_ptr += 1;
556 word_ptr += 2;
557 num_words += 2;
558 }
559
560 if ((control_word >> 20) & 1)
561 printf("unknown bit 20 enabled\n");
562
563 if ((control_word >> 21) & 1) {
564 print_vector_field("vadd", word_ptr, *beginning_ptr, tabs);
565 beginning_ptr += 1;
566 word_ptr += 3;
567 num_words += 3;
568 }
569
570 if ((control_word >> 22) & 1)
571 printf("unknown bit 22 enabled\n");
572
573 if ((control_word >> 23) & 1) {
574 print_scalar_field("smul", word_ptr, *beginning_ptr, tabs);
575 beginning_ptr += 1;
576 word_ptr += 2;
577 num_words += 2;
578 }
579
580 if ((control_word >> 24) & 1)
581 printf("unknown bit 24 enabled\n");
582
583 if ((control_word >> 25) & 1) {
584 print_vector_field("lut", word_ptr, *beginning_ptr, tabs);
585 beginning_ptr += 1;
586 word_ptr += 3;
587 num_words += 3;
588 }
589
590 if ((control_word >> 26) & 1) {
591 print_compact_branch_writeout_field(*word_ptr);
592 word_ptr += 1;
593 num_words += 1;
594 }
595
596 if ((control_word >> 27) & 1) {
597 print_extended_branch_writeout_field((uint8_t *) word_ptr);
598 word_ptr += 3;
599 num_words += 3;
600 }
601
602 if (num_quad_words > (num_words + 7) / 8) {
603 assert(num_quad_words == (num_words + 15) / 8);
604 //Assume that the extra quadword is constants
605 void *consts = words + (4 * num_quad_words - 4);
606
607 if (is_embedded_constant_int) {
608 if (is_embedded_constant_half) {
609 int16_t *sconsts = (int16_t *) consts;
610 printf("sconstants %d, %d, %d, %d\n",
611 sconsts[0],
612 sconsts[1],
613 sconsts[2],
614 sconsts[3]);
615 } else {
616 int32_t *iconsts = (int32_t *) consts;
617 printf("iconstants %d, %d, %d, %d\n",
618 iconsts[0],
619 iconsts[1],
620 iconsts[2],
621 iconsts[3]);
622 }
623 } else {
624 if (is_embedded_constant_half) {
625 uint16_t *hconsts = (uint16_t *) consts;
626 printf("hconstants %g, %g, %g, %g\n",
627 _mesa_half_to_float(hconsts[0]),
628 _mesa_half_to_float(hconsts[1]),
629 _mesa_half_to_float(hconsts[2]),
630 _mesa_half_to_float(hconsts[3]));
631 } else {
632 uint32_t *fconsts = (uint32_t *) consts;
633 printf("fconstants %g, %g, %g, %g\n",
634 float_bitcast(fconsts[0]),
635 float_bitcast(fconsts[1]),
636 float_bitcast(fconsts[2]),
637 float_bitcast(fconsts[3]));
638 }
639
640 }
641 }
642 }
643
644 /* Swizzle/mask formats are common between load/store ops and texture ops, it
645 * looks like... */
646
647 static void
648 print_swizzle(uint32_t swizzle)
649 {
650 unsigned i;
651
652 if (swizzle != 0xE4) {
653 printf(".");
654
655 for (i = 0; i < 4; i++)
656 printf("%c", "xyzw"[(swizzle >> (2 * i)) & 3]);
657 }
658 }
659
660 static void
661 print_mask(uint32_t mask)
662 {
663 unsigned i;
664
665 if (mask != 0xF) {
666 printf(".");
667
668 for (i = 0; i < 4; i++)
669 if (mask & (1 << i))
670 printf("%c", "xyzw"[i]);
671
672 /* Handle degenerate case */
673 if (mask == 0)
674 printf("0");
675 }
676 }
677
678 static void
679 print_varying_parameters(midgard_load_store_word *word)
680 {
681 midgard_varying_parameter param;
682 unsigned v = word->varying_parameters;
683 memcpy(&param, &v, sizeof(param));
684
685 if (param.is_varying) {
686 /* If a varying, there are qualifiers */
687 if (param.flat)
688 printf(".flat");
689
690 if (param.interpolation != midgard_interp_default) {
691 if (param.interpolation == midgard_interp_centroid)
692 printf(".centroid");
693 else
694 printf(".interp%d", param.interpolation);
695 }
696 } else if (param.flat || param.interpolation) {
697 printf(" /* is_varying not set but varying metadata attached */");
698 }
699
700 if (param.zero1 || param.zero2)
701 printf(" /* zero tripped, %d %d */ ", param.zero1, param.zero2);
702 }
703
704 static bool
705 is_op_varying(unsigned op)
706 {
707 switch (op) {
708 case midgard_op_store_vary_16:
709 case midgard_op_store_vary_32:
710 case midgard_op_load_vary_16:
711 case midgard_op_load_vary_32:
712 return true;
713 }
714
715 return false;
716 }
717
718 static void
719 print_load_store_instr(uint64_t data,
720 unsigned tabs)
721 {
722 midgard_load_store_word *word = (midgard_load_store_word *) &data;
723
724 print_ld_st_opcode(word->op);
725
726 if (is_op_varying(word->op))
727 print_varying_parameters(word);
728
729 printf(" r%d", word->reg);
730 print_mask(word->mask);
731
732 int address = word->address;
733
734 if (word->op == midgard_op_load_uniform_32) {
735 /* Uniforms use their own addressing scheme */
736
737 int lo = word->varying_parameters >> 7;
738 int hi = word->address;
739
740 /* TODO: Combine fields logically */
741 address = (hi << 3) | lo;
742 }
743
744 printf(", %d", address);
745
746 print_swizzle(word->swizzle);
747
748 printf(", 0x%X\n", word->unknown);
749 }
750
751 static void
752 print_load_store_word(uint32_t *word, unsigned tabs)
753 {
754 midgard_load_store *load_store = (midgard_load_store *) word;
755
756 if (load_store->word1 != 3) {
757 print_load_store_instr(load_store->word1, tabs);
758 }
759
760 if (load_store->word2 != 3) {
761 print_load_store_instr(load_store->word2, tabs);
762 }
763 }
764
765 static void
766 print_texture_reg(bool full, bool select, bool upper)
767 {
768 if (full)
769 printf("r%d", REG_TEX_BASE + select);
770 else
771 printf("hr%d", (REG_TEX_BASE + select) * 2 + upper);
772
773 if (full && upper)
774 printf("// error: out full / upper mutually exclusive\n");
775
776 }
777
778 static void
779 print_texture_format(int format)
780 {
781 /* Act like a modifier */
782 printf(".");
783
784 switch (format) {
785 DEFINE_CASE(TEXTURE_2D, "2d");
786 DEFINE_CASE(TEXTURE_3D, "3d");
787
788 default:
789 printf("fmt_%d", format);
790 break;
791 }
792 }
793
794 static void
795 print_texture_op(int format)
796 {
797 /* Act like a modifier */
798 printf(".");
799
800 switch (format) {
801 DEFINE_CASE(TEXTURE_OP_NORMAL, "normal");
802 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelfetch");
803
804 default:
805 printf("op_%d", format);
806 break;
807 }
808 }
809
810 #undef DEFINE_CASE
811
812 static void
813 print_texture_word(uint32_t *word, unsigned tabs)
814 {
815 midgard_texture_word *texture = (midgard_texture_word *) word;
816
817 /* Instruction family, like ALU words have theirs */
818 printf("texture");
819
820 /* Broad category of texture operation in question */
821 print_texture_op(texture->op);
822
823 /* Specific format in question */
824 print_texture_format(texture->format);
825
826 /* Instruction "modifiers" parallel the ALU instructions. First group
827 * are modifiers that act alone */
828
829 if (!texture->filter)
830 printf(".raw");
831
832 if (texture->shadow)
833 printf(".shadow");
834
835 if (texture->cont)
836 printf(".cont");
837
838 if (texture->last)
839 printf(".last");
840
841 /* Second set are modifiers which take an extra argument each */
842
843 if (texture->has_offset)
844 printf(".offset");
845
846 if (texture->bias)
847 printf(".bias");
848
849 printf(" ");
850
851 print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper);
852 print_mask(texture->mask);
853 printf(", ");
854
855 printf("texture%d, ", texture->texture_handle);
856
857 printf("sampler%d", texture->sampler_handle);
858 print_swizzle(texture->swizzle);
859 printf(", ");
860
861 print_texture_reg(/*texture->in_reg_full*/true, texture->in_reg_select, texture->in_reg_upper);
862 printf(".%c%c, ", "xyzw"[texture->in_reg_swizzle_left],
863 "xyzw"[texture->in_reg_swizzle_right]);
864
865 /* TODO: can offsets be full words? */
866 if (texture->has_offset) {
867 print_texture_reg(false, texture->offset_reg_select, texture->offset_reg_upper);
868 printf(", ");
869 }
870
871 if (texture->bias)
872 printf("%f, ", texture->bias / 256.0f);
873
874 printf("\n");
875
876 /* While not zero in general, for these simple instructions the
877 * following unknowns are zero, so we don't include them */
878
879 if (texture->unknown1 ||
880 texture->unknown2 ||
881 texture->unknown3 ||
882 texture->unknown4 ||
883 texture->unknownA ||
884 texture->unknownB ||
885 texture->unknown8 ||
886 texture->unknown9) {
887 printf("// unknown1 = 0x%x\n", texture->unknown1);
888 printf("// unknown2 = 0x%x\n", texture->unknown2);
889 printf("// unknown3 = 0x%x\n", texture->unknown3);
890 printf("// unknown4 = 0x%x\n", texture->unknown4);
891 printf("// unknownA = 0x%x\n", texture->unknownA);
892 printf("// unknownB = 0x%x\n", texture->unknownB);
893 printf("// unknown8 = 0x%x\n", texture->unknown8);
894 printf("// unknown9 = 0x%x\n", texture->unknown9);
895 }
896
897 /* Similarly, if no offset is applied, these are zero. If an offset
898 * -is- applied, or gradients are used, etc, these are nonzero but
899 * largely unknown still. */
900
901 if (texture->offset_unknown1 ||
902 texture->offset_reg_select ||
903 texture->offset_reg_upper ||
904 texture->offset_unknown4 ||
905 texture->offset_unknown5 ||
906 texture->offset_unknown6 ||
907 texture->offset_unknown7 ||
908 texture->offset_unknown8 ||
909 texture->offset_unknown9) {
910 printf("// offset_unknown1 = 0x%x\n", texture->offset_unknown1);
911 printf("// offset_reg_select = 0x%x\n", texture->offset_reg_select);
912 printf("// offset_reg_upper = 0x%x\n", texture->offset_reg_upper);
913 printf("// offset_unknown4 = 0x%x\n", texture->offset_unknown4);
914 printf("// offset_unknown5 = 0x%x\n", texture->offset_unknown5);
915 printf("// offset_unknown6 = 0x%x\n", texture->offset_unknown6);
916 printf("// offset_unknown7 = 0x%x\n", texture->offset_unknown7);
917 printf("// offset_unknown8 = 0x%x\n", texture->offset_unknown8);
918 printf("// offset_unknown9 = 0x%x\n", texture->offset_unknown9);
919 }
920
921 /* Don't blow up */
922 if (texture->unknown7 != 0x1)
923 printf("// (!) unknown7 = %d\n", texture->unknown7);
924 }
925
926 void
927 disassemble_midgard(uint8_t *code, size_t size)
928 {
929 uint32_t *words = (uint32_t *) code;
930 unsigned num_words = size / 4;
931 int tabs = 0;
932
933 bool prefetch_flag = false;
934
935 unsigned i = 0;
936
937 while (i < num_words) {
938 unsigned num_quad_words = midgard_word_size[words[i] & 0xF];
939
940 switch (midgard_word_types[words[i] & 0xF]) {
941 case midgard_word_type_texture:
942 print_texture_word(&words[i], tabs);
943 break;
944
945 case midgard_word_type_load_store:
946 print_load_store_word(&words[i], tabs);
947 break;
948
949 case midgard_word_type_alu:
950 print_alu_word(&words[i], num_quad_words, tabs);
951
952 if (prefetch_flag)
953 return;
954
955 /* Reset word static analysis state */
956 is_embedded_constant_half = false;
957 is_embedded_constant_int = false;
958
959 break;
960
961 default:
962 printf("Unknown word type %u:\n", words[i] & 0xF);
963 num_quad_words = 1;
964 print_quad_word(&words[i], tabs);
965 printf("\n");
966 break;
967 }
968
969 printf("\n");
970
971 unsigned next = (words[i] & 0xF0) >> 4;
972
973 i += 4 * num_quad_words;
974
975 /* Break based on instruction prefetch flag */
976
977 if (i < num_words && next == 1) {
978 prefetch_flag = true;
979
980 if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu)
981 return;
982 }
983 }
984
985 return;
986 }