pan/midgard/disasm: Fix printing 8-bit/16-bit masks
[mesa.git] / src / 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 <ctype.h>
32 #include <string.h>
33 #include "midgard.h"
34 #include "midgard-parse.h"
35 #include "midgard_ops.h"
36 #include "disassemble.h"
37 #include "helpers.h"
38 #include "util/half_float.h"
39 #include "util/u_math.h"
40
41 #define DEFINE_CASE(define, str) case define: { printf(str); break; }
42
43 static bool is_instruction_int = false;
44
45 /* Stats */
46
47 static struct midgard_disasm_stats midg_stats;
48
49 /* Prints a short form of the tag for branching, the minimum needed to be
50 * legible and unambiguous */
51
52 static void
53 print_tag_short(unsigned tag)
54 {
55 switch (midgard_word_types[tag]) {
56 case midgard_word_type_texture:
57 printf("tex/%X", tag);
58 break;
59
60 case midgard_word_type_load_store:
61 printf("ldst");
62 break;
63
64 case midgard_word_type_alu:
65 printf("alu%u/%X", midgard_word_size[tag], tag);
66 break;
67
68 default:
69 printf("%s%X", (tag > 0) ? "" : "unk", tag);
70 break;
71 }
72 }
73
74 static void
75 print_alu_opcode(midgard_alu_op op)
76 {
77 bool int_op = false;
78
79 if (alu_opcode_props[op].name) {
80 printf("%s", alu_opcode_props[op].name);
81
82 int_op = midgard_is_integer_op(op);
83 } else
84 printf("alu_op_%02X", op);
85
86 /* For constant analysis */
87 is_instruction_int = int_op;
88 }
89
90 static void
91 print_ld_st_opcode(midgard_load_store_op op)
92 {
93 if (load_store_opcode_names[op])
94 printf("%s", load_store_opcode_names[op]);
95 else
96 printf("ldst_op_%02X", op);
97 }
98
99 static bool is_embedded_constant_half = false;
100 static bool is_embedded_constant_int = false;
101
102 static char
103 prefix_for_bits(unsigned bits)
104 {
105 switch (bits) {
106 case 8:
107 return 'q';
108 case 16:
109 return 'h';
110 case 64:
111 return 'd';
112 default:
113 return 0;
114 }
115 }
116
117 /* For static analysis to ensure all registers are written at least once before
118 * use along the source code path (TODO: does this break done for complex CF?)
119 */
120
121 uint16_t midg_ever_written = 0;
122
123 static void
124 print_reg(unsigned reg, unsigned bits)
125 {
126 /* Perform basic static analysis for expanding constants correctly */
127
128 if (reg == 26) {
129 is_embedded_constant_int = is_instruction_int;
130 is_embedded_constant_half = (bits < 32);
131 }
132
133 unsigned uniform_reg = 23 - reg;
134 bool is_uniform = false;
135
136 /* For r8-r15, it could be a work or uniform. We distinguish based on
137 * the fact work registers are ALWAYS written before use, but uniform
138 * registers are NEVER written before use. */
139
140 if ((reg >= 8 && reg < 16) && !(midg_ever_written & (1 << reg)))
141 is_uniform = true;
142
143 /* r16-r23 are always uniform */
144
145 if (reg >= 16 && reg <= 23)
146 is_uniform = true;
147
148 /* Update the uniform count appropriately */
149
150 if (is_uniform)
151 midg_stats.uniform_count =
152 MAX2(uniform_reg + 1, midg_stats.uniform_count);
153
154 char prefix = prefix_for_bits(bits);
155
156 if (prefix)
157 putchar(prefix);
158
159 printf("r%u", reg);
160 }
161
162 static char *outmod_names_float[4] = {
163 "",
164 ".pos",
165 ".unk2",
166 ".sat"
167 };
168
169 static char *outmod_names_int[4] = {
170 ".isat",
171 ".usat",
172 "",
173 ".hi"
174 };
175
176 static char *srcmod_names_int[4] = {
177 "sext(",
178 "zext(",
179 "",
180 "("
181 };
182
183 static void
184 print_outmod(unsigned outmod, bool is_int)
185 {
186 printf("%s", is_int ? outmod_names_int[outmod] :
187 outmod_names_float[outmod]);
188 }
189
190 static void
191 print_quad_word(uint32_t *words, unsigned tabs)
192 {
193 unsigned i;
194
195 for (i = 0; i < 4; i++)
196 printf("0x%08X%s ", words[i], i == 3 ? "" : ",");
197
198 printf("\n");
199 }
200
201 static const char components[16] = "xyzwefghijklmnop";
202
203 /* Helper to print 4 chars of a swizzle */
204 static void
205 print_swizzle_helper(unsigned swizzle, bool upper)
206 {
207 for (unsigned i = 0; i < 4; ++i) {
208 unsigned c = (swizzle >> (i * 2)) & 3;
209 c += upper*4;
210 printf("%c", components[c]);
211 }
212 }
213
214 /* Helper to print 8 chars of a swizzle, duplicating over */
215 static void
216 print_swizzle_helper_8(unsigned swizzle, bool upper)
217 {
218 for (unsigned i = 0; i < 4; ++i) {
219 unsigned c = (swizzle >> (i * 2)) & 3;
220 c *= 2;
221 c += upper*8;
222 printf("%c%c", components[c], components[c+1]);
223 }
224 }
225
226 static void
227 print_swizzle_vec16(unsigned swizzle, bool rep_high, bool rep_low,
228 midgard_dest_override override)
229 {
230 printf(".");
231
232 if (override == midgard_dest_override_upper) {
233 if (rep_high)
234 printf(" /* rep_high */ ");
235 if (rep_low)
236 printf(" /* rep_low */ ");
237
238 if (!rep_high && rep_low)
239 print_swizzle_helper_8(swizzle, true);
240 else
241 print_swizzle_helper_8(swizzle, false);
242 } else {
243 print_swizzle_helper_8(swizzle, rep_high & 1);
244 print_swizzle_helper_8(swizzle, !(rep_low & 1));
245 }
246 }
247
248 static void
249 print_swizzle_vec8(unsigned swizzle, bool rep_high, bool rep_low)
250 {
251 printf(".");
252
253 print_swizzle_helper(swizzle, rep_high & 1);
254 print_swizzle_helper(swizzle, !(rep_low & 1));
255 }
256
257 static void
258 print_swizzle_vec4(unsigned swizzle, bool rep_high, bool rep_low)
259 {
260 if (rep_high)
261 printf(" /* rep_high */ ");
262 if (rep_low)
263 printf(" /* rep_low */ ");
264
265 if (swizzle == 0xE4) return; /* xyzw */
266
267 printf(".");
268 print_swizzle_helper(swizzle, 0);
269 }
270 static void
271 print_swizzle_vec2(unsigned swizzle, bool rep_high, bool rep_low)
272 {
273 if (rep_high)
274 printf(" /* rep_high */ ");
275 if (rep_low)
276 printf(" /* rep_low */ ");
277
278 if (swizzle == 0xE4) return; /* XY */
279
280 printf(".");
281
282 for (unsigned i = 0; i < 4; i += 2) {
283 unsigned a = (swizzle >> (i * 2)) & 3;
284 unsigned b = (swizzle >> ((i+1) * 2)) & 3;
285
286 /* Normally we're adjacent, but if there's an issue, don't make
287 * it ambiguous */
288
289 if (a & 0x1)
290 printf("[%c%c]", components[a], components[b]);
291 else if (a == b)
292 printf("%c", components[a >> 1]);
293 else if (b == (a + 1))
294 printf("%c", "XY"[a >> 1]);
295 else
296 printf("[%c%c]", components[a], components[b]);
297 }
298 }
299
300 static int
301 bits_for_mode(midgard_reg_mode mode)
302 {
303 switch (mode) {
304 case midgard_reg_mode_8:
305 return 8;
306 case midgard_reg_mode_16:
307 return 16;
308 case midgard_reg_mode_32:
309 return 32;
310 case midgard_reg_mode_64:
311 return 64;
312 default:
313 unreachable("Invalid reg mode");
314 return 0;
315 }
316 }
317
318 static int
319 bits_for_mode_halved(midgard_reg_mode mode, bool half)
320 {
321 unsigned bits = bits_for_mode(mode);
322
323 if (half)
324 bits >>= 1;
325
326 return bits;
327 }
328
329 static void
330 print_vector_src(unsigned src_binary,
331 midgard_reg_mode mode, unsigned reg,
332 midgard_dest_override override, bool is_int)
333 {
334 midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary;
335
336 /* Modifiers change meaning depending on the op's context */
337
338 midgard_int_mod int_mod = src->mod;
339
340 if (is_int) {
341 printf("%s", srcmod_names_int[int_mod]);
342 } else {
343 if (src->mod & MIDGARD_FLOAT_MOD_NEG)
344 printf("-");
345
346 if (src->mod & MIDGARD_FLOAT_MOD_ABS)
347 printf("abs(");
348 }
349
350 //register
351 unsigned bits = bits_for_mode_halved(mode, src->half);
352 print_reg(reg, bits);
353
354 //swizzle
355 if (bits == 16)
356 print_swizzle_vec8(src->swizzle, src->rep_high, src->rep_low);
357 else if (bits == 8)
358 print_swizzle_vec16(src->swizzle, src->rep_high, src->rep_low, override);
359 else if (bits == 32)
360 print_swizzle_vec4(src->swizzle, src->rep_high, src->rep_low);
361 else if (bits == 64)
362 print_swizzle_vec2(src->swizzle, src->rep_high, src->rep_low);
363
364 /* Since we wrapped with a function-looking thing */
365
366 if (is_int && int_mod == midgard_int_shift)
367 printf(") << %u", bits);
368 else if ((is_int && (int_mod != midgard_int_normal))
369 || (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS))
370 printf(")");
371 }
372
373 static uint16_t
374 decode_vector_imm(unsigned src2_reg, unsigned imm)
375 {
376 uint16_t ret;
377 ret = src2_reg << 11;
378 ret |= (imm & 0x7) << 8;
379 ret |= (imm >> 3) & 0xFF;
380 return ret;
381 }
382
383 static void
384 print_immediate(uint16_t imm)
385 {
386 if (is_instruction_int)
387 printf("#%u", imm);
388 else
389 printf("#%g", _mesa_half_to_float(imm));
390 }
391
392 static void
393 update_dest(unsigned reg)
394 {
395 /* We should record writes as marking this as a work register. Store
396 * the max register in work_count; we'll add one at the end */
397
398 if (reg < 16) {
399 midg_stats.work_count = MAX2(reg, midg_stats.work_count);
400 midg_ever_written |= (1 << reg);
401 }
402 }
403
404 static void
405 print_dest(unsigned reg, midgard_reg_mode mode, midgard_dest_override override)
406 {
407 /* Depending on the mode and override, we determine the type of
408 * destination addressed. Absent an override, we address just the
409 * type of the operation itself */
410
411 unsigned bits = bits_for_mode(mode);
412
413 if (override != midgard_dest_override_none)
414 bits /= 2;
415
416 update_dest(reg);
417 print_reg(reg, bits);
418 }
419
420 static void
421 print_mask_vec16(uint8_t mask, midgard_dest_override override)
422 {
423 printf(".");
424
425 for (unsigned i = 0; i < 8; i++) {
426 if (mask & (1 << i))
427 printf("%c%c",
428 components[i*2 + 0],
429 components[i*2 + 1]);
430 }
431 }
432
433 /* For 16-bit+ masks, we read off from the 8-bit mask field. For 16-bit (vec8),
434 * it's just one bit per channel, easy peasy. For 32-bit (vec4), it's one bit
435 * per channel with one duplicate bit in the middle. For 64-bit (vec2), it's
436 * one-bit per channel with _3_ duplicate bits in the middle. Basically, just
437 * subdividing the 128-bit word in 16-bit increments. For 64-bit, we uppercase
438 * the mask to make it obvious what happened */
439
440 static void
441 print_mask(uint8_t mask, unsigned bits, midgard_dest_override override)
442 {
443 if (bits == 8) {
444 print_mask_vec16(mask, override);
445 return;
446 }
447
448 /* Skip 'complete' masks */
449
450 if (override == midgard_dest_override_none) {
451 if (bits >= 32 && mask == 0xFF) return;
452
453 if (bits == 16) {
454 if (mask == 0x0F)
455 return;
456 else if (mask == 0xF0) {
457 printf("'");
458 return;
459 }
460 }
461 }
462
463 printf(".");
464
465 unsigned skip = (bits / 16);
466 bool uppercase = bits > 32;
467 bool tripped = false;
468
469 /* To apply an upper destination override, we "shift" the alphabet.
470 * E.g. with an upper override on 32-bit, instead of xyzw, print efgh.
471 * For upper 16-bit, instead of xyzwefgh, print ijklmnop */
472
473 const char *alphabet = components;
474
475 if (override == midgard_dest_override_upper) {
476 unsigned components = 128 / bits;
477 alphabet += components;
478 }
479
480 for (unsigned i = 0; i < 8; i += skip) {
481 bool a = (mask & (1 << i)) != 0;
482
483 for (unsigned j = 1; j < skip; ++j) {
484 bool dupe = (mask & (1 << (i + j))) != 0;
485 tripped |= (dupe != a);
486 }
487
488 if (a) {
489 char c = alphabet[i / skip];
490
491 if (uppercase)
492 c = toupper(c);
493
494 printf("%c", c);
495 }
496 }
497
498 if (tripped)
499 printf(" /* %X */", mask);
500 }
501
502 /* Prints the 4-bit masks found in texture and load/store ops, as opposed to
503 * the 8-bit masks found in (vector) ALU ops */
504
505 static void
506 print_mask_4(unsigned mask)
507 {
508 if (mask == 0xF) return;
509
510 printf(".");
511
512 for (unsigned i = 0; i < 4; ++i) {
513 bool a = (mask & (1 << i)) != 0;
514 if (a)
515 printf("%c", components[i]);
516 }
517 }
518
519 static void
520 print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
521 unsigned tabs)
522 {
523 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
524 midgard_vector_alu *alu_field = (midgard_vector_alu *) words;
525 midgard_reg_mode mode = alu_field->reg_mode;
526 unsigned override = alu_field->dest_override;
527
528 /* For now, prefix instruction names with their unit, until we
529 * understand how this works on a deeper level */
530 printf("%s.", name);
531
532 print_alu_opcode(alu_field->op);
533
534 /* Postfix with the size to disambiguate if necessary */
535 char postfix = prefix_for_bits(bits_for_mode(mode));
536 bool size_ambiguous = override != midgard_dest_override_none;
537
538 if (size_ambiguous)
539 printf("%c", postfix ? postfix : 'r');
540
541 /* Print the outmod, if there is one */
542 print_outmod(alu_field->outmod,
543 midgard_is_integer_out_op(alu_field->op));
544
545 printf(" ");
546
547 /* Mask denoting status of 8-lanes */
548 uint8_t mask = alu_field->mask;
549
550 /* First, print the destination */
551 print_dest(reg_info->out_reg, mode, alu_field->dest_override);
552
553 if (override != midgard_dest_override_none) {
554 bool modeable = (mode != midgard_reg_mode_8);
555 bool known = override != 0x3; /* Unused value */
556
557 if (!(modeable && known))
558 printf("/* do%u */ ", override);
559 }
560
561 print_mask(mask, bits_for_mode(mode), override);
562
563 printf(", ");
564
565 bool is_int = midgard_is_integer_op(alu_field->op);
566 print_vector_src(alu_field->src1, mode, reg_info->src1_reg, override, is_int);
567
568 printf(", ");
569
570 if (reg_info->src2_imm) {
571 uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2);
572 print_immediate(imm);
573 } else {
574 print_vector_src(alu_field->src2, mode,
575 reg_info->src2_reg, override, is_int);
576 }
577
578 midg_stats.instruction_count++;
579 printf("\n");
580 }
581
582 static void
583 print_scalar_src(unsigned src_binary, unsigned reg)
584 {
585 midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary;
586
587 if (src->negate)
588 printf("-");
589
590 if (src->abs)
591 printf("abs(");
592
593 print_reg(reg, src->full ? 32 : 16);
594
595 unsigned c = src->component;
596
597 if (src->full) {
598 assert((c & 1) == 0);
599 c >>= 1;
600 }
601
602 printf(".%c", components[c]);
603
604 if (src->abs)
605 printf(")");
606
607 }
608
609 static uint16_t
610 decode_scalar_imm(unsigned src2_reg, unsigned imm)
611 {
612 uint16_t ret;
613 ret = src2_reg << 11;
614 ret |= (imm & 3) << 9;
615 ret |= (imm & 4) << 6;
616 ret |= (imm & 0x38) << 2;
617 ret |= imm >> 6;
618 return ret;
619 }
620
621 static void
622 print_scalar_field(const char *name, uint16_t *words, uint16_t reg_word,
623 unsigned tabs)
624 {
625 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
626 midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words;
627
628 if (alu_field->unknown)
629 printf("scalar ALU unknown bit set\n");
630
631 printf("%s.", name);
632 print_alu_opcode(alu_field->op);
633 print_outmod(alu_field->outmod,
634 midgard_is_integer_out_op(alu_field->op));
635 printf(" ");
636
637 bool full = alu_field->output_full;
638 update_dest(reg_info->out_reg);
639 print_reg(reg_info->out_reg, full ? 32 : 16);
640 unsigned c = alu_field->output_component;
641
642 if (full) {
643 assert((c & 1) == 0);
644 c >>= 1;
645 }
646
647 printf(".%c, ", components[c]);
648
649 print_scalar_src(alu_field->src1, reg_info->src1_reg);
650
651 printf(", ");
652
653 if (reg_info->src2_imm) {
654 uint16_t imm = decode_scalar_imm(reg_info->src2_reg,
655 alu_field->src2);
656 print_immediate(imm);
657 } else
658 print_scalar_src(alu_field->src2, reg_info->src2_reg);
659
660 midg_stats.instruction_count++;
661 printf("\n");
662 }
663
664 static void
665 print_branch_op(unsigned op)
666 {
667 switch (op) {
668 case midgard_jmp_writeout_op_branch_uncond:
669 printf("uncond.");
670 break;
671
672 case midgard_jmp_writeout_op_branch_cond:
673 printf("cond.");
674 break;
675
676 case midgard_jmp_writeout_op_writeout:
677 printf("write.");
678 break;
679
680 case midgard_jmp_writeout_op_tilebuffer_pending:
681 printf("tilebuffer.");
682 break;
683
684 case midgard_jmp_writeout_op_discard:
685 printf("discard.");
686 break;
687
688 default:
689 printf("unk%u.", op);
690 break;
691 }
692 }
693
694 static void
695 print_branch_cond(int cond)
696 {
697 switch (cond) {
698 case midgard_condition_write0:
699 printf("write0");
700 break;
701
702 case midgard_condition_false:
703 printf("false");
704 break;
705
706 case midgard_condition_true:
707 printf("true");
708 break;
709
710 case midgard_condition_always:
711 printf("always");
712 break;
713
714 default:
715 printf("unk%X", cond);
716 break;
717 }
718 }
719
720 static void
721 print_compact_branch_writeout_field(uint16_t word)
722 {
723 midgard_jmp_writeout_op op = word & 0x7;
724
725 switch (op) {
726 case midgard_jmp_writeout_op_branch_uncond: {
727 midgard_branch_uncond br_uncond;
728 memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond));
729 printf("br.uncond ");
730
731 if (br_uncond.unknown != 1)
732 printf("unknown:%u, ", br_uncond.unknown);
733
734 if (br_uncond.offset >= 0)
735 printf("+");
736
737 printf("%d -> ", br_uncond.offset);
738 print_tag_short(br_uncond.dest_tag);
739 printf("\n");
740
741 break;
742 }
743
744 case midgard_jmp_writeout_op_branch_cond:
745 case midgard_jmp_writeout_op_writeout:
746 case midgard_jmp_writeout_op_discard:
747 default: {
748 midgard_branch_cond br_cond;
749 memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond));
750
751 printf("br.");
752
753 print_branch_op(br_cond.op);
754 print_branch_cond(br_cond.cond);
755
756 printf(" ");
757
758 if (br_cond.offset >= 0)
759 printf("+");
760
761 printf("%d -> ", br_cond.offset);
762 print_tag_short(br_cond.dest_tag);
763 printf("\n");
764
765 break;
766 }
767 }
768
769 midg_stats.instruction_count++;
770 }
771
772 static void
773 print_extended_branch_writeout_field(uint8_t *words)
774 {
775 midgard_branch_extended br;
776 memcpy((char *) &br, (char *) words, sizeof(br));
777
778 printf("brx.");
779
780 print_branch_op(br.op);
781
782 /* Condition codes are a LUT in the general case, but simply repeated 8 times for single-channel conditions.. Check this. */
783
784 bool single_channel = true;
785
786 for (unsigned i = 0; i < 16; i += 2) {
787 single_channel &= (((br.cond >> i) & 0x3) == (br.cond & 0x3));
788 }
789
790 if (single_channel)
791 print_branch_cond(br.cond & 0x3);
792 else
793 printf("lut%X", br.cond);
794
795 if (br.unknown)
796 printf(".unknown%u", br.unknown);
797
798 printf(" ");
799
800 if (br.offset >= 0)
801 printf("+");
802
803 printf("%d -> ", br.offset);
804 print_tag_short(br.dest_tag);
805 printf("\n");
806
807 midg_stats.instruction_count++;
808 }
809
810 static unsigned
811 num_alu_fields_enabled(uint32_t control_word)
812 {
813 unsigned ret = 0;
814
815 if ((control_word >> 17) & 1)
816 ret++;
817
818 if ((control_word >> 19) & 1)
819 ret++;
820
821 if ((control_word >> 21) & 1)
822 ret++;
823
824 if ((control_word >> 23) & 1)
825 ret++;
826
827 if ((control_word >> 25) & 1)
828 ret++;
829
830 return ret;
831 }
832
833 static float
834 float_bitcast(uint32_t integer)
835 {
836 union {
837 uint32_t i;
838 float f;
839 } v;
840
841 v.i = integer;
842 return v.f;
843 }
844
845 static void
846 print_alu_word(uint32_t *words, unsigned num_quad_words,
847 unsigned tabs)
848 {
849 uint32_t control_word = words[0];
850 uint16_t *beginning_ptr = (uint16_t *)(words + 1);
851 unsigned num_fields = num_alu_fields_enabled(control_word);
852 uint16_t *word_ptr = beginning_ptr + num_fields;
853 unsigned num_words = 2 + num_fields;
854
855 if ((control_word >> 16) & 1)
856 printf("unknown bit 16 enabled\n");
857
858 if ((control_word >> 17) & 1) {
859 print_vector_field("vmul", word_ptr, *beginning_ptr, tabs);
860 beginning_ptr += 1;
861 word_ptr += 3;
862 num_words += 3;
863 }
864
865 if ((control_word >> 18) & 1)
866 printf("unknown bit 18 enabled\n");
867
868 if ((control_word >> 19) & 1) {
869 print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs);
870 beginning_ptr += 1;
871 word_ptr += 2;
872 num_words += 2;
873 }
874
875 if ((control_word >> 20) & 1)
876 printf("unknown bit 20 enabled\n");
877
878 if ((control_word >> 21) & 1) {
879 print_vector_field("vadd", word_ptr, *beginning_ptr, tabs);
880 beginning_ptr += 1;
881 word_ptr += 3;
882 num_words += 3;
883 }
884
885 if ((control_word >> 22) & 1)
886 printf("unknown bit 22 enabled\n");
887
888 if ((control_word >> 23) & 1) {
889 print_scalar_field("smul", word_ptr, *beginning_ptr, tabs);
890 beginning_ptr += 1;
891 word_ptr += 2;
892 num_words += 2;
893 }
894
895 if ((control_word >> 24) & 1)
896 printf("unknown bit 24 enabled\n");
897
898 if ((control_word >> 25) & 1) {
899 print_vector_field("lut", word_ptr, *beginning_ptr, tabs);
900 word_ptr += 3;
901 num_words += 3;
902 }
903
904 if ((control_word >> 26) & 1) {
905 print_compact_branch_writeout_field(*word_ptr);
906 word_ptr += 1;
907 num_words += 1;
908 }
909
910 if ((control_word >> 27) & 1) {
911 print_extended_branch_writeout_field((uint8_t *) word_ptr);
912 word_ptr += 3;
913 num_words += 3;
914 }
915
916 if (num_quad_words > (num_words + 7) / 8) {
917 assert(num_quad_words == (num_words + 15) / 8);
918 //Assume that the extra quadword is constants
919 void *consts = words + (4 * num_quad_words - 4);
920
921 if (is_embedded_constant_int) {
922 if (is_embedded_constant_half) {
923 int16_t *sconsts = (int16_t *) consts;
924 printf("sconstants %d, %d, %d, %d\n",
925 sconsts[0],
926 sconsts[1],
927 sconsts[2],
928 sconsts[3]);
929 } else {
930 uint32_t *iconsts = (uint32_t *) consts;
931 printf("iconstants 0x%X, 0x%X, 0x%X, 0x%X\n",
932 iconsts[0],
933 iconsts[1],
934 iconsts[2],
935 iconsts[3]);
936 }
937 } else {
938 if (is_embedded_constant_half) {
939 uint16_t *hconsts = (uint16_t *) consts;
940 printf("hconstants %g, %g, %g, %g\n",
941 _mesa_half_to_float(hconsts[0]),
942 _mesa_half_to_float(hconsts[1]),
943 _mesa_half_to_float(hconsts[2]),
944 _mesa_half_to_float(hconsts[3]));
945 } else {
946 uint32_t *fconsts = (uint32_t *) consts;
947 printf("fconstants %g, %g, %g, %g\n",
948 float_bitcast(fconsts[0]),
949 float_bitcast(fconsts[1]),
950 float_bitcast(fconsts[2]),
951 float_bitcast(fconsts[3]));
952 }
953
954 }
955 }
956 }
957
958 static void
959 print_varying_parameters(midgard_load_store_word *word)
960 {
961 midgard_varying_parameter param;
962 unsigned v = word->varying_parameters;
963 memcpy(&param, &v, sizeof(param));
964
965 if (param.is_varying) {
966 /* If a varying, there are qualifiers */
967 if (param.flat)
968 printf(".flat");
969
970 if (param.interpolation != midgard_interp_default) {
971 if (param.interpolation == midgard_interp_centroid)
972 printf(".centroid");
973 else
974 printf(".interp%d", param.interpolation);
975 }
976
977 if (param.modifier != midgard_varying_mod_none) {
978 if (param.modifier == midgard_varying_mod_perspective_w)
979 printf(".perspectivew");
980 else if (param.modifier == midgard_varying_mod_perspective_z)
981 printf(".perspectivez");
982 else
983 printf(".mod%d", param.modifier);
984 }
985 } else if (param.flat || param.interpolation || param.modifier) {
986 printf(" /* is_varying not set but varying metadata attached */");
987 }
988
989 if (param.zero0 || param.zero1 || param.zero2)
990 printf(" /* zero tripped, %u %u %u */ ", param.zero0, param.zero1, param.zero2);
991 }
992
993 static bool
994 is_op_varying(unsigned op)
995 {
996 switch (op) {
997 case midgard_op_st_vary_16:
998 case midgard_op_st_vary_32:
999 case midgard_op_st_vary_32i:
1000 case midgard_op_st_vary_32u:
1001 case midgard_op_ld_vary_16:
1002 case midgard_op_ld_vary_32:
1003 case midgard_op_ld_vary_32i:
1004 case midgard_op_ld_vary_32u:
1005 return true;
1006 }
1007
1008 return false;
1009 }
1010
1011 static bool
1012 is_op_attribute(unsigned op)
1013 {
1014 switch (op) {
1015 case midgard_op_ld_attr_16:
1016 case midgard_op_ld_attr_32:
1017 case midgard_op_ld_attr_32i:
1018 case midgard_op_ld_attr_32u:
1019 return true;
1020 }
1021
1022 return false;
1023 }
1024
1025 static void
1026 print_load_store_arg(uint8_t arg, unsigned index)
1027 {
1028 /* Try to interpret as a register */
1029 midgard_ldst_register_select sel;
1030 memcpy(&sel, &arg, sizeof(arg));
1031
1032 /* If unknown is set, we're not sure what this is or how to
1033 * interpret it. But if it's zero, we get it. */
1034
1035 if (sel.unknown) {
1036 printf("0x%02X", arg);
1037 return;
1038 }
1039
1040 unsigned reg = REGISTER_LDST_BASE + sel.select;
1041 char comp = components[sel.component];
1042
1043 printf("r%u.%c", reg, comp);
1044
1045 /* Only print a shift if it's non-zero. Shifts only make sense for the
1046 * second index. For the first, we're not sure what it means yet */
1047
1048 if (index == 1) {
1049 if (sel.shift)
1050 printf(" << %u", sel.shift);
1051 } else {
1052 printf(" /* %X */", sel.shift);
1053 }
1054 }
1055
1056 static void
1057 update_stats(signed *stat, unsigned address)
1058 {
1059 if (*stat >= 0)
1060 *stat = MAX2(*stat, address + 1);
1061 }
1062
1063 static void
1064 print_load_store_instr(uint64_t data,
1065 unsigned tabs)
1066 {
1067 midgard_load_store_word *word = (midgard_load_store_word *) &data;
1068
1069 print_ld_st_opcode(word->op);
1070
1071 unsigned address = word->address;
1072
1073 if (is_op_varying(word->op)) {
1074 print_varying_parameters(word);
1075
1076 /* Do some analysis: check if direct cacess */
1077
1078 if ((word->arg_2 == 0x1E) && midg_stats.varying_count >= 0)
1079 update_stats(&midg_stats.varying_count, address);
1080 else
1081 midg_stats.varying_count = -16;
1082 } else if (is_op_attribute(word->op)) {
1083 if ((word->arg_2 == 0x1E) && midg_stats.attribute_count >= 0)
1084 update_stats(&midg_stats.attribute_count, address);
1085 else
1086 midg_stats.attribute_count = -16;
1087 }
1088
1089 printf(" r%u", word->reg);
1090 print_mask_4(word->mask);
1091
1092 if (!OP_IS_STORE(word->op))
1093 update_dest(word->reg);
1094
1095 bool is_ubo = OP_IS_UBO_READ(word->op);
1096
1097 if (is_ubo) {
1098 /* UBOs use their own addressing scheme */
1099
1100 int lo = word->varying_parameters >> 7;
1101 int hi = word->address;
1102
1103 /* TODO: Combine fields logically */
1104 address = (hi << 3) | lo;
1105 }
1106
1107 printf(", %u", address);
1108
1109 print_swizzle_vec4(word->swizzle, false, false);
1110
1111 printf(", ");
1112
1113 if (is_ubo) {
1114 printf("ubo%u", word->arg_1);
1115 update_stats(&midg_stats.uniform_buffer_count, word->arg_1);
1116 } else
1117 print_load_store_arg(word->arg_1, 0);
1118
1119 printf(", ");
1120 print_load_store_arg(word->arg_2, 1);
1121 printf(" /* %X */\n", word->varying_parameters);
1122
1123 midg_stats.instruction_count++;
1124 }
1125
1126 static void
1127 print_load_store_word(uint32_t *word, unsigned tabs)
1128 {
1129 midgard_load_store *load_store = (midgard_load_store *) word;
1130
1131 if (load_store->word1 != 3) {
1132 print_load_store_instr(load_store->word1, tabs);
1133 }
1134
1135 if (load_store->word2 != 3) {
1136 print_load_store_instr(load_store->word2, tabs);
1137 }
1138 }
1139
1140 static void
1141 print_texture_reg(bool full, bool select, bool upper)
1142 {
1143 if (full)
1144 printf("r%d", REG_TEX_BASE + select);
1145 else
1146 printf("hr%d", (REG_TEX_BASE + select) * 2 + upper);
1147
1148 if (full && upper)
1149 printf("// error: out full / upper mutually exclusive\n");
1150
1151 }
1152
1153 static void
1154 print_texture_reg_triple(unsigned triple)
1155 {
1156 bool full = triple & 1;
1157 bool select = triple & 2;
1158 bool upper = triple & 4;
1159
1160 print_texture_reg(full, select, upper);
1161 }
1162
1163 static void
1164 print_texture_reg_select(uint8_t u)
1165 {
1166 midgard_tex_register_select sel;
1167 memcpy(&sel, &u, sizeof(u));
1168
1169 if (!sel.full)
1170 printf("h");
1171
1172 printf("r%u", REG_TEX_BASE + sel.select);
1173
1174 unsigned component = sel.component;
1175
1176 /* Use the upper half in half-reg mode */
1177 if (sel.upper) {
1178 assert(!sel.full);
1179 component += 4;
1180 }
1181
1182 printf(".%c", components[component]);
1183
1184 assert(sel.zero == 0);
1185 }
1186
1187 static void
1188 print_texture_format(int format)
1189 {
1190 /* Act like a modifier */
1191 printf(".");
1192
1193 switch (format) {
1194 DEFINE_CASE(MALI_TEX_1D, "1d");
1195 DEFINE_CASE(MALI_TEX_2D, "2d");
1196 DEFINE_CASE(MALI_TEX_3D, "3d");
1197 DEFINE_CASE(MALI_TEX_CUBE, "cube");
1198
1199 default:
1200 unreachable("Bad format");
1201 }
1202 }
1203
1204 static bool
1205 midgard_op_has_helpers(unsigned op, bool gather)
1206 {
1207 if (gather)
1208 return true;
1209
1210 switch (op) {
1211 case TEXTURE_OP_NORMAL:
1212 case TEXTURE_OP_DFDX:
1213 case TEXTURE_OP_DFDY:
1214 return true;
1215 default:
1216 return false;
1217 }
1218 }
1219
1220 static void
1221 print_texture_op(unsigned op, bool gather)
1222 {
1223 /* Act like a bare name, like ESSL functions */
1224
1225 if (gather) {
1226 printf("textureGather");
1227
1228 unsigned component = op >> 4;
1229 unsigned bottom = op & 0xF;
1230
1231 if (bottom != 0x2)
1232 printf("_unk%u", bottom);
1233
1234 printf(".%c", components[component]);
1235 return;
1236 }
1237
1238 switch (op) {
1239 DEFINE_CASE(TEXTURE_OP_NORMAL, "texture");
1240 DEFINE_CASE(TEXTURE_OP_LOD, "textureLod");
1241 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelFetch");
1242 DEFINE_CASE(TEXTURE_OP_DFDX, "dFdx");
1243 DEFINE_CASE(TEXTURE_OP_DFDY, "dFdy");
1244
1245 default:
1246 printf("tex_%X", op);
1247 break;
1248 }
1249 }
1250
1251 static bool
1252 texture_op_takes_bias(unsigned op)
1253 {
1254 return op == TEXTURE_OP_NORMAL;
1255 }
1256
1257 static char
1258 sampler_type_name(enum mali_sampler_type t)
1259 {
1260 switch (t) {
1261 case MALI_SAMPLER_FLOAT:
1262 return 'f';
1263 case MALI_SAMPLER_UNSIGNED:
1264 return 'u';
1265 case MALI_SAMPLER_SIGNED:
1266 return 'i';
1267 default:
1268 return '?';
1269 }
1270
1271 }
1272
1273 #undef DEFINE_CASE
1274
1275 static void
1276 print_texture_word(uint32_t *word, unsigned tabs)
1277 {
1278 midgard_texture_word *texture = (midgard_texture_word *) word;
1279
1280 midg_stats.helper_invocations |=
1281 midgard_op_has_helpers(texture->op, texture->is_gather);
1282
1283 /* Broad category of texture operation in question */
1284 print_texture_op(texture->op, texture->is_gather);
1285
1286 /* Specific format in question */
1287 print_texture_format(texture->format);
1288
1289 /* Instruction "modifiers" parallel the ALU instructions. */
1290
1291 if (texture->shadow)
1292 printf(".shadow");
1293
1294 if (texture->cont)
1295 printf(".cont");
1296
1297 if (texture->last)
1298 printf(".last");
1299
1300 /* Output modifiers are always interpreted floatly */
1301 print_outmod(texture->outmod, false);
1302
1303 printf(" ");
1304
1305 print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper);
1306 print_mask_4(texture->mask);
1307 printf(", ");
1308
1309 /* Depending on whether we read from textures directly or indirectly,
1310 * we may be able to update our analysis */
1311
1312 if (texture->texture_register) {
1313 printf("texture[");
1314 print_texture_reg_select(texture->texture_handle);
1315 printf("], ");
1316
1317 /* Indirect, tut tut */
1318 midg_stats.texture_count = -16;
1319 } else {
1320 printf("texture%u, ", texture->texture_handle);
1321 update_stats(&midg_stats.texture_count, texture->texture_handle);
1322 }
1323
1324 /* Print the type, GL style */
1325 printf("%csampler", sampler_type_name(texture->sampler_type));
1326
1327 if (texture->sampler_register) {
1328 printf("[");
1329 print_texture_reg_select(texture->sampler_handle);
1330 printf("]");
1331
1332 midg_stats.sampler_count = -16;
1333 } else {
1334 printf("%u", texture->sampler_handle);
1335 update_stats(&midg_stats.sampler_count, texture->sampler_handle);
1336 }
1337
1338 print_swizzle_vec4(texture->swizzle, false, false);
1339 printf(", ");
1340
1341 print_texture_reg(texture->in_reg_full, texture->in_reg_select, texture->in_reg_upper);
1342 print_swizzle_vec4(texture->in_reg_swizzle, false, false);
1343
1344 /* There is *always* an offset attached. Of
1345 * course, that offset is just immediate #0 for a
1346 * GLES call that doesn't take an offset. If there
1347 * is a non-negative non-zero offset, this is
1348 * specified in immediate offset mode, with the
1349 * values in the offset_* fields as immediates. If
1350 * this is a negative offset, we instead switch to
1351 * a register offset mode, where the offset_*
1352 * fields become register triplets */
1353
1354 if (texture->offset_register) {
1355 printf(" + ");
1356 print_texture_reg_triple(texture->offset_x);
1357
1358 /* The less questions you ask, the better. */
1359
1360 unsigned swizzle_lo, swizzle_hi;
1361 unsigned orig_y = texture->offset_y;
1362 unsigned orig_z = texture->offset_z;
1363
1364 memcpy(&swizzle_lo, &orig_y, sizeof(unsigned));
1365 memcpy(&swizzle_hi, &orig_z, sizeof(unsigned));
1366
1367 /* Duplicate hi swizzle over */
1368 assert(swizzle_hi < 4);
1369 swizzle_hi = (swizzle_hi << 2) | swizzle_hi;
1370
1371 unsigned swiz = (swizzle_lo << 4) | swizzle_hi;
1372 unsigned reversed = util_bitreverse(swiz) >> 24;
1373 print_swizzle_vec4(reversed, false, false);
1374
1375 printf(", ");
1376 } else if (texture->offset_x || texture->offset_y || texture->offset_z) {
1377 /* Only select ops allow negative immediate offsets, verify */
1378
1379 bool neg_x = texture->offset_x < 0;
1380 bool neg_y = texture->offset_y < 0;
1381 bool neg_z = texture->offset_z < 0;
1382 bool any_neg = neg_x || neg_y || neg_z;
1383
1384 if (any_neg && texture->op != TEXTURE_OP_TEXEL_FETCH)
1385 printf("/* invalid negative */ ");
1386
1387 /* Regardless, just print the immediate offset */
1388
1389 printf(" + <%d, %d, %d>, ",
1390 texture->offset_x,
1391 texture->offset_y,
1392 texture->offset_z);
1393 } else {
1394 printf(", ");
1395 }
1396
1397 char lod_operand = texture_op_takes_bias(texture->op) ? '+' : '=';
1398
1399 if (texture->lod_register) {
1400 printf("lod %c ", lod_operand);
1401 print_texture_reg_select(texture->bias);
1402 printf(", ");
1403
1404 if (texture->bias_int)
1405 printf(" /* bias_int = 0x%X */", texture->bias_int);
1406 } else if (texture->op == TEXTURE_OP_TEXEL_FETCH) {
1407 /* For texel fetch, the int LOD is in the fractional place and
1408 * there is no fraction / possibility of bias. We *always* have
1409 * an explicit LOD, even if it's zero. */
1410
1411 if (texture->bias_int)
1412 printf(" /* bias_int = 0x%X */ ", texture->bias_int);
1413
1414 printf("lod = %u, ", texture->bias);
1415 } else if (texture->bias || texture->bias_int) {
1416 signed bias_int = texture->bias_int;
1417 float bias_frac = texture->bias / 256.0f;
1418 float bias = bias_int + bias_frac;
1419
1420 bool is_bias = texture_op_takes_bias(texture->op);
1421 char sign = (bias >= 0.0) ? '+' : '-';
1422 char operand = is_bias ? sign : '=';
1423
1424 printf("lod %c %f, ", operand, fabsf(bias));
1425 }
1426
1427 printf("\n");
1428
1429 /* While not zero in general, for these simple instructions the
1430 * following unknowns are zero, so we don't include them */
1431
1432 if (texture->unknown4 ||
1433 texture->unknownA ||
1434 texture->unknown8) {
1435 printf("// unknown4 = 0x%x\n", texture->unknown4);
1436 printf("// unknownA = 0x%x\n", texture->unknownA);
1437 printf("// unknown8 = 0x%x\n", texture->unknown8);
1438 }
1439
1440 midg_stats.instruction_count++;
1441 }
1442
1443 struct midgard_disasm_stats
1444 disassemble_midgard(uint8_t *code, size_t size)
1445 {
1446 uint32_t *words = (uint32_t *) code;
1447 unsigned num_words = size / 4;
1448 int tabs = 0;
1449
1450 bool prefetch_flag = false;
1451
1452 int last_next_tag = -1;
1453
1454 unsigned i = 0;
1455
1456 /* Stats for shader-db */
1457 memset(&midg_stats, 0, sizeof(midg_stats));
1458 midg_ever_written = 0;
1459
1460 while (i < num_words) {
1461 unsigned tag = words[i] & 0xF;
1462 unsigned next_tag = (words[i] >> 4) & 0xF;
1463 unsigned num_quad_words = midgard_word_size[tag];
1464
1465 /* Check the tag */
1466 if (last_next_tag > 1) {
1467 if (last_next_tag != tag) {
1468 printf("/* TAG ERROR got ");
1469 print_tag_short(tag);
1470 printf(" expected ");
1471 print_tag_short(last_next_tag);
1472 printf(" */ ");
1473 }
1474 } else {
1475 /* TODO: Check ALU case */
1476 }
1477
1478 last_next_tag = next_tag;
1479
1480 switch (midgard_word_types[tag]) {
1481 case midgard_word_type_texture:
1482 print_texture_word(&words[i], tabs);
1483 break;
1484
1485 case midgard_word_type_load_store:
1486 print_load_store_word(&words[i], tabs);
1487 break;
1488
1489 case midgard_word_type_alu:
1490 print_alu_word(&words[i], num_quad_words, tabs);
1491
1492 /* Reset word static analysis state */
1493 is_embedded_constant_half = false;
1494 is_embedded_constant_int = false;
1495
1496 break;
1497
1498 default:
1499 printf("Unknown word type %u:\n", words[i] & 0xF);
1500 num_quad_words = 1;
1501 print_quad_word(&words[i], tabs);
1502 printf("\n");
1503 break;
1504 }
1505
1506 if (prefetch_flag && midgard_word_types[tag] == midgard_word_type_alu)
1507 break;
1508
1509 printf("\n");
1510
1511 unsigned next = (words[i] & 0xF0) >> 4;
1512
1513 /* We are parsing per bundle anyway */
1514 midg_stats.bundle_count++;
1515 midg_stats.quadword_count += num_quad_words;
1516
1517 /* Break based on instruction prefetch flag */
1518
1519 if (i < num_words && next == 1) {
1520 prefetch_flag = true;
1521
1522 if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu)
1523 break;
1524 }
1525
1526 i += 4 * num_quad_words;
1527 }
1528
1529 /* We computed work_count as max_work_registers, so add one to get the
1530 * count. If no work registers are written, you still have one work
1531 * reported, which is exactly what the hardware expects */
1532
1533 midg_stats.work_count++;
1534
1535 return midg_stats;
1536 }