panfrost/midgard: Add load/store opcodes
[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 "helpers.h"
36 #include "util/half_float.h"
37
38 #define DEFINE_CASE(define, str) case define: { printf(str); break; }
39
40 static bool is_instruction_int = false;
41
42 static void
43 print_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
58 static void
59 print_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
67 static bool is_embedded_constant_half = false;
68 static bool is_embedded_constant_int = false;
69
70 static char
71 prefix_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
85 static void
86 print_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
109 static char *outmod_names[4] = {
110 "",
111 ".pos",
112 ".int",
113 ".sat"
114 };
115
116 static void
117 print_outmod(midgard_outmod outmod)
118 {
119 printf("%s", outmod_names[outmod]);
120 }
121
122 static void
123 print_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
133 static void
134 print_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
258 static uint16_t
259 decode_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
268 static void
269 print_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
277 static int
278 bits_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
294 static void
295 print_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
341 static void
342 print_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 *)&reg_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
431 static void
432 print_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
456 static uint16_t
457 decode_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
468 static void
469 print_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 *)&reg_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
508 static void
509 print_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
538 static void
539 print_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
564 static void
565 print_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
612 static void
613 print_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
645 static unsigned
646 num_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
668 static float
669 float_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
680 static void
681 print_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
797 static void
798 print_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
810 static void
811 print_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
828 static void
829 print_varying_parameters(midgard_load_store_word *word)
830 {
831 midgard_varying_parameter param;
832 unsigned v = word->varying_parameters;
833 memcpy(&param, &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
854 static bool
855 is_op_varying(unsigned op)
856 {
857 switch (op) {
858 case midgard_op_st_vary_16:
859 case midgard_op_st_vary_32:
860 case midgard_op_ld_vary_16:
861 case midgard_op_ld_vary_32:
862 return true;
863 }
864
865 return false;
866 }
867
868 static void
869 print_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_ld_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
901 static void
902 print_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
915 static void
916 print_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
928 static void
929 print_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
945 static void
946 print_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
963 static void
964 print_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
1077 void
1078 disassemble_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 }