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