pan/midgard: Correct issues in disassemble.c
[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 unsigned
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 return bits;
420 }
421
422 static void
423 print_mask_vec16(uint8_t mask, midgard_dest_override override)
424 {
425 printf(".");
426
427 if (override == midgard_dest_override_none) {
428 for (unsigned i = 0; i < 8; i++) {
429 if (mask & (1 << i))
430 printf("%c%c",
431 components[i*2 + 0],
432 components[i*2 + 1]);
433 }
434 } else {
435 bool upper = (override == midgard_dest_override_upper);
436
437 for (unsigned i = 0; i < 8; i++) {
438 if (mask & (1 << i))
439 printf("%c", components[i + (upper ? 8 : 0)]);
440 }
441 }
442 }
443
444 /* For 16-bit+ masks, we read off from the 8-bit mask field. For 16-bit (vec8),
445 * it's just one bit per channel, easy peasy. For 32-bit (vec4), it's one bit
446 * per channel with one duplicate bit in the middle. For 64-bit (vec2), it's
447 * one-bit per channel with _3_ duplicate bits in the middle. Basically, just
448 * subdividing the 128-bit word in 16-bit increments. For 64-bit, we uppercase
449 * the mask to make it obvious what happened */
450
451 static void
452 print_mask(uint8_t mask, unsigned bits, midgard_dest_override override)
453 {
454 if (bits == 8) {
455 print_mask_vec16(mask, override);
456 return;
457 }
458
459 if (bits < 16) {
460 /* Shouldn't happen but with junk / out-of-spec shaders it
461 * would cause an infinite loop */
462
463 printf("/* XXX: bits = %u */", bits);
464 return;
465 }
466
467 /* Skip 'complete' masks */
468
469 if (bits >= 32 && mask == 0xFF) return;
470
471 if (bits == 16) {
472 if (mask == 0x0F)
473 return;
474 else if (mask == 0xF0) {
475 printf("'");
476 return;
477 }
478 }
479
480 printf(".");
481
482 unsigned skip = (bits / 16);
483 bool uppercase = bits > 32;
484 bool tripped = false;
485
486 for (unsigned i = 0; i < 8; i += skip) {
487 bool a = (mask & (1 << i)) != 0;
488
489 for (unsigned j = 1; j < skip; ++j) {
490 bool dupe = (mask & (1 << (i + j))) != 0;
491 tripped |= (dupe != a);
492 }
493
494 if (a) {
495 char c = components[i / skip];
496
497 if (uppercase)
498 c = toupper(c);
499
500 printf("%c", c);
501 }
502 }
503
504 if (tripped)
505 printf(" /* %X */", mask);
506 }
507
508 /* Prints the 4-bit masks found in texture and load/store ops, as opposed to
509 * the 8-bit masks found in (vector) ALU ops */
510
511 static void
512 print_mask_4(unsigned mask)
513 {
514 if (mask == 0xF) return;
515
516 printf(".");
517
518 for (unsigned i = 0; i < 4; ++i) {
519 bool a = (mask & (1 << i)) != 0;
520 if (a)
521 printf("%c", components[i]);
522 }
523 }
524
525 static void
526 print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
527 unsigned tabs)
528 {
529 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
530 midgard_vector_alu *alu_field = (midgard_vector_alu *) words;
531 midgard_reg_mode mode = alu_field->reg_mode;
532 unsigned override = alu_field->dest_override;
533
534 /* For now, prefix instruction names with their unit, until we
535 * understand how this works on a deeper level */
536 printf("%s.", name);
537
538 print_alu_opcode(alu_field->op);
539
540 /* Postfix with the size to disambiguate if necessary */
541 char postfix = prefix_for_bits(bits_for_mode(mode));
542 bool size_ambiguous = override != midgard_dest_override_none;
543
544 if (size_ambiguous)
545 printf("%c", postfix ? postfix : 'r');
546
547 /* Print the outmod, if there is one */
548 print_outmod(alu_field->outmod,
549 midgard_is_integer_out_op(alu_field->op));
550
551 printf(" ");
552
553 /* Mask denoting status of 8-lanes */
554 uint8_t mask = alu_field->mask;
555
556 /* First, print the destination */
557 unsigned dest_size =
558 print_dest(reg_info->out_reg, mode, alu_field->dest_override);
559
560 /* Apply the destination override to the mask */
561
562 if (mode == midgard_reg_mode_32 || mode == midgard_reg_mode_64) {
563 if (override == midgard_dest_override_lower)
564 mask &= 0x0F;
565 else if (override == midgard_dest_override_upper)
566 mask &= 0xF0;
567 } else if (mode == midgard_reg_mode_16
568 && override == midgard_dest_override_lower) {
569 /* stub */
570 }
571
572 if (override != midgard_dest_override_none) {
573 bool modeable = (mode != midgard_reg_mode_8);
574 bool known = override != 0x3; /* Unused value */
575
576 if (!(modeable && known))
577 printf("/* do%u */ ", override);
578 }
579
580 print_mask(mask, dest_size, override);
581
582 printf(", ");
583
584 bool is_int = midgard_is_integer_op(alu_field->op);
585 print_vector_src(alu_field->src1, mode, reg_info->src1_reg, override, is_int);
586
587 printf(", ");
588
589 if (reg_info->src2_imm) {
590 uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2);
591 print_immediate(imm);
592 } else {
593 print_vector_src(alu_field->src2, mode,
594 reg_info->src2_reg, override, is_int);
595 }
596
597 midg_stats.instruction_count++;
598 printf("\n");
599 }
600
601 static void
602 print_scalar_src(unsigned src_binary, unsigned reg)
603 {
604 midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary;
605
606 if (src->negate)
607 printf("-");
608
609 if (src->abs)
610 printf("abs(");
611
612 print_reg(reg, src->full ? 32 : 16);
613
614 unsigned c = src->component;
615
616 if (src->full) {
617 assert((c & 1) == 0);
618 c >>= 1;
619 }
620
621 printf(".%c", components[c]);
622
623 if (src->abs)
624 printf(")");
625
626 }
627
628 static uint16_t
629 decode_scalar_imm(unsigned src2_reg, unsigned imm)
630 {
631 uint16_t ret;
632 ret = src2_reg << 11;
633 ret |= (imm & 3) << 9;
634 ret |= (imm & 4) << 6;
635 ret |= (imm & 0x38) << 2;
636 ret |= imm >> 6;
637 return ret;
638 }
639
640 static void
641 print_scalar_field(const char *name, uint16_t *words, uint16_t reg_word,
642 unsigned tabs)
643 {
644 midgard_reg_info *reg_info = (midgard_reg_info *)&reg_word;
645 midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words;
646
647 if (alu_field->unknown)
648 printf("scalar ALU unknown bit set\n");
649
650 printf("%s.", name);
651 print_alu_opcode(alu_field->op);
652 print_outmod(alu_field->outmod,
653 midgard_is_integer_out_op(alu_field->op));
654 printf(" ");
655
656 bool full = alu_field->output_full;
657 update_dest(reg_info->out_reg);
658 print_reg(reg_info->out_reg, full ? 32 : 16);
659 unsigned c = alu_field->output_component;
660
661 if (full) {
662 assert((c & 1) == 0);
663 c >>= 1;
664 }
665
666 printf(".%c, ", components[c]);
667
668 print_scalar_src(alu_field->src1, reg_info->src1_reg);
669
670 printf(", ");
671
672 if (reg_info->src2_imm) {
673 uint16_t imm = decode_scalar_imm(reg_info->src2_reg,
674 alu_field->src2);
675 print_immediate(imm);
676 } else
677 print_scalar_src(alu_field->src2, reg_info->src2_reg);
678
679 midg_stats.instruction_count++;
680 printf("\n");
681 }
682
683 static void
684 print_branch_op(unsigned op)
685 {
686 switch (op) {
687 case midgard_jmp_writeout_op_branch_uncond:
688 printf("uncond.");
689 break;
690
691 case midgard_jmp_writeout_op_branch_cond:
692 printf("cond.");
693 break;
694
695 case midgard_jmp_writeout_op_writeout:
696 printf("write.");
697 break;
698
699 case midgard_jmp_writeout_op_tilebuffer_pending:
700 printf("tilebuffer.");
701 break;
702
703 case midgard_jmp_writeout_op_discard:
704 printf("discard.");
705 break;
706
707 default:
708 printf("unk%u.", op);
709 break;
710 }
711 }
712
713 static void
714 print_branch_cond(int cond)
715 {
716 switch (cond) {
717 case midgard_condition_write0:
718 printf("write0");
719 break;
720
721 case midgard_condition_false:
722 printf("false");
723 break;
724
725 case midgard_condition_true:
726 printf("true");
727 break;
728
729 case midgard_condition_always:
730 printf("always");
731 break;
732
733 default:
734 printf("unk%X", cond);
735 break;
736 }
737 }
738
739 static void
740 print_compact_branch_writeout_field(uint16_t word)
741 {
742 midgard_jmp_writeout_op op = word & 0x7;
743
744 switch (op) {
745 case midgard_jmp_writeout_op_branch_uncond: {
746 midgard_branch_uncond br_uncond;
747 memcpy((char *) &br_uncond, (char *) &word, sizeof(br_uncond));
748 printf("br.uncond ");
749
750 if (br_uncond.unknown != 1)
751 printf("unknown:%u, ", br_uncond.unknown);
752
753 if (br_uncond.offset >= 0)
754 printf("+");
755
756 printf("%d -> ", br_uncond.offset);
757 print_tag_short(br_uncond.dest_tag);
758 printf("\n");
759
760 break;
761 }
762
763 case midgard_jmp_writeout_op_branch_cond:
764 case midgard_jmp_writeout_op_writeout:
765 case midgard_jmp_writeout_op_discard:
766 default: {
767 midgard_branch_cond br_cond;
768 memcpy((char *) &br_cond, (char *) &word, sizeof(br_cond));
769
770 printf("br.");
771
772 print_branch_op(br_cond.op);
773 print_branch_cond(br_cond.cond);
774
775 printf(" ");
776
777 if (br_cond.offset >= 0)
778 printf("+");
779
780 printf("%d -> ", br_cond.offset);
781 print_tag_short(br_cond.dest_tag);
782 printf("\n");
783
784 break;
785 }
786 }
787
788 midg_stats.instruction_count++;
789 }
790
791 static void
792 print_extended_branch_writeout_field(uint8_t *words)
793 {
794 midgard_branch_extended br;
795 memcpy((char *) &br, (char *) words, sizeof(br));
796
797 printf("brx.");
798
799 print_branch_op(br.op);
800
801 /* Condition codes are a LUT in the general case, but simply repeated 8 times for single-channel conditions.. Check this. */
802
803 bool single_channel = true;
804
805 for (unsigned i = 0; i < 16; i += 2) {
806 single_channel &= (((br.cond >> i) & 0x3) == (br.cond & 0x3));
807 }
808
809 if (single_channel)
810 print_branch_cond(br.cond & 0x3);
811 else
812 printf("lut%X", br.cond);
813
814 if (br.unknown)
815 printf(".unknown%u", br.unknown);
816
817 printf(" ");
818
819 if (br.offset >= 0)
820 printf("+");
821
822 printf("%d -> ", br.offset);
823 print_tag_short(br.dest_tag);
824 printf("\n");
825
826 midg_stats.instruction_count++;
827 }
828
829 static unsigned
830 num_alu_fields_enabled(uint32_t control_word)
831 {
832 unsigned ret = 0;
833
834 if ((control_word >> 17) & 1)
835 ret++;
836
837 if ((control_word >> 19) & 1)
838 ret++;
839
840 if ((control_word >> 21) & 1)
841 ret++;
842
843 if ((control_word >> 23) & 1)
844 ret++;
845
846 if ((control_word >> 25) & 1)
847 ret++;
848
849 return ret;
850 }
851
852 static float
853 float_bitcast(uint32_t integer)
854 {
855 union {
856 uint32_t i;
857 float f;
858 } v;
859
860 v.i = integer;
861 return v.f;
862 }
863
864 static void
865 print_alu_word(uint32_t *words, unsigned num_quad_words,
866 unsigned tabs)
867 {
868 uint32_t control_word = words[0];
869 uint16_t *beginning_ptr = (uint16_t *)(words + 1);
870 unsigned num_fields = num_alu_fields_enabled(control_word);
871 uint16_t *word_ptr = beginning_ptr + num_fields;
872 unsigned num_words = 2 + num_fields;
873
874 if ((control_word >> 16) & 1)
875 printf("unknown bit 16 enabled\n");
876
877 if ((control_word >> 17) & 1) {
878 print_vector_field("vmul", word_ptr, *beginning_ptr, tabs);
879 beginning_ptr += 1;
880 word_ptr += 3;
881 num_words += 3;
882 }
883
884 if ((control_word >> 18) & 1)
885 printf("unknown bit 18 enabled\n");
886
887 if ((control_word >> 19) & 1) {
888 print_scalar_field("sadd", word_ptr, *beginning_ptr, tabs);
889 beginning_ptr += 1;
890 word_ptr += 2;
891 num_words += 2;
892 }
893
894 if ((control_word >> 20) & 1)
895 printf("unknown bit 20 enabled\n");
896
897 if ((control_word >> 21) & 1) {
898 print_vector_field("vadd", word_ptr, *beginning_ptr, tabs);
899 beginning_ptr += 1;
900 word_ptr += 3;
901 num_words += 3;
902 }
903
904 if ((control_word >> 22) & 1)
905 printf("unknown bit 22 enabled\n");
906
907 if ((control_word >> 23) & 1) {
908 print_scalar_field("smul", word_ptr, *beginning_ptr, tabs);
909 beginning_ptr += 1;
910 word_ptr += 2;
911 num_words += 2;
912 }
913
914 if ((control_word >> 24) & 1)
915 printf("unknown bit 24 enabled\n");
916
917 if ((control_word >> 25) & 1) {
918 print_vector_field("lut", word_ptr, *beginning_ptr, tabs);
919 word_ptr += 3;
920 num_words += 3;
921 }
922
923 if ((control_word >> 26) & 1) {
924 print_compact_branch_writeout_field(*word_ptr);
925 word_ptr += 1;
926 num_words += 1;
927 }
928
929 if ((control_word >> 27) & 1) {
930 print_extended_branch_writeout_field((uint8_t *) word_ptr);
931 word_ptr += 3;
932 num_words += 3;
933 }
934
935 if (num_quad_words > (num_words + 7) / 8) {
936 assert(num_quad_words == (num_words + 15) / 8);
937 //Assume that the extra quadword is constants
938 void *consts = words + (4 * num_quad_words - 4);
939
940 if (is_embedded_constant_int) {
941 if (is_embedded_constant_half) {
942 int16_t *sconsts = (int16_t *) consts;
943 printf("sconstants %d, %d, %d, %d\n",
944 sconsts[0],
945 sconsts[1],
946 sconsts[2],
947 sconsts[3]);
948 } else {
949 uint32_t *iconsts = (uint32_t *) consts;
950 printf("iconstants 0x%X, 0x%X, 0x%X, 0x%X\n",
951 iconsts[0],
952 iconsts[1],
953 iconsts[2],
954 iconsts[3]);
955 }
956 } else {
957 if (is_embedded_constant_half) {
958 uint16_t *hconsts = (uint16_t *) consts;
959 printf("hconstants %g, %g, %g, %g\n",
960 _mesa_half_to_float(hconsts[0]),
961 _mesa_half_to_float(hconsts[1]),
962 _mesa_half_to_float(hconsts[2]),
963 _mesa_half_to_float(hconsts[3]));
964 } else {
965 uint32_t *fconsts = (uint32_t *) consts;
966 printf("fconstants %g, %g, %g, %g\n",
967 float_bitcast(fconsts[0]),
968 float_bitcast(fconsts[1]),
969 float_bitcast(fconsts[2]),
970 float_bitcast(fconsts[3]));
971 }
972
973 }
974 }
975 }
976
977 static void
978 print_varying_parameters(midgard_load_store_word *word)
979 {
980 midgard_varying_parameter param;
981 unsigned v = word->varying_parameters;
982 memcpy(&param, &v, sizeof(param));
983
984 if (param.is_varying) {
985 /* If a varying, there are qualifiers */
986 if (param.flat)
987 printf(".flat");
988
989 if (param.interpolation != midgard_interp_default) {
990 if (param.interpolation == midgard_interp_centroid)
991 printf(".centroid");
992 else
993 printf(".interp%d", param.interpolation);
994 }
995
996 if (param.modifier != midgard_varying_mod_none) {
997 if (param.modifier == midgard_varying_mod_perspective_w)
998 printf(".perspectivew");
999 else if (param.modifier == midgard_varying_mod_perspective_z)
1000 printf(".perspectivez");
1001 else
1002 printf(".mod%d", param.modifier);
1003 }
1004 } else if (param.flat || param.interpolation || param.modifier) {
1005 printf(" /* is_varying not set but varying metadata attached */");
1006 }
1007
1008 if (param.zero0 || param.zero1 || param.zero2)
1009 printf(" /* zero tripped, %u %u %u */ ", param.zero0, param.zero1, param.zero2);
1010 }
1011
1012 static bool
1013 is_op_varying(unsigned op)
1014 {
1015 switch (op) {
1016 case midgard_op_st_vary_16:
1017 case midgard_op_st_vary_32:
1018 case midgard_op_st_vary_32i:
1019 case midgard_op_st_vary_32u:
1020 case midgard_op_ld_vary_16:
1021 case midgard_op_ld_vary_32:
1022 case midgard_op_ld_vary_32i:
1023 case midgard_op_ld_vary_32u:
1024 return true;
1025 }
1026
1027 return false;
1028 }
1029
1030 static bool
1031 is_op_attribute(unsigned op)
1032 {
1033 switch (op) {
1034 case midgard_op_ld_attr_16:
1035 case midgard_op_ld_attr_32:
1036 case midgard_op_ld_attr_32i:
1037 case midgard_op_ld_attr_32u:
1038 return true;
1039 }
1040
1041 return false;
1042 }
1043
1044 static void
1045 print_load_store_arg(uint8_t arg, unsigned index)
1046 {
1047 /* Try to interpret as a register */
1048 midgard_ldst_register_select sel;
1049 memcpy(&sel, &arg, sizeof(arg));
1050
1051 /* If unknown is set, we're not sure what this is or how to
1052 * interpret it. But if it's zero, we get it. */
1053
1054 if (sel.unknown) {
1055 printf("0x%02X", arg);
1056 return;
1057 }
1058
1059 unsigned reg = REGISTER_LDST_BASE + sel.select;
1060 char comp = components[sel.component];
1061
1062 printf("r%u.%c", reg, comp);
1063
1064 /* Only print a shift if it's non-zero. Shifts only make sense for the
1065 * second index. For the first, we're not sure what it means yet */
1066
1067 if (index == 1) {
1068 if (sel.shift)
1069 printf(" << %u", sel.shift);
1070 } else {
1071 printf(" /* %X */", sel.shift);
1072 }
1073 }
1074
1075 static void
1076 update_stats(signed *stat, unsigned address)
1077 {
1078 if (*stat >= 0)
1079 *stat = MAX2(*stat, address + 1);
1080 }
1081
1082 static void
1083 print_load_store_instr(uint64_t data,
1084 unsigned tabs)
1085 {
1086 midgard_load_store_word *word = (midgard_load_store_word *) &data;
1087
1088 print_ld_st_opcode(word->op);
1089
1090 unsigned address = word->address;
1091
1092 if (is_op_varying(word->op)) {
1093 print_varying_parameters(word);
1094
1095 /* Do some analysis: check if direct cacess */
1096
1097 if ((word->arg_2 == 0x1E) && midg_stats.varying_count >= 0)
1098 update_stats(&midg_stats.varying_count, address);
1099 else
1100 midg_stats.varying_count = -16;
1101 } else if (is_op_attribute(word->op)) {
1102 if ((word->arg_2 == 0x1E) && midg_stats.attribute_count >= 0)
1103 update_stats(&midg_stats.attribute_count, address);
1104 else
1105 midg_stats.attribute_count = -16;
1106 }
1107
1108 printf(" r%u", word->reg);
1109 print_mask_4(word->mask);
1110
1111 if (!OP_IS_STORE(word->op))
1112 update_dest(word->reg);
1113
1114 bool is_ubo = OP_IS_UBO_READ(word->op);
1115
1116 if (is_ubo) {
1117 /* UBOs use their own addressing scheme */
1118
1119 int lo = word->varying_parameters >> 7;
1120 int hi = word->address;
1121
1122 /* TODO: Combine fields logically */
1123 address = (hi << 3) | lo;
1124 }
1125
1126 printf(", %u", address);
1127
1128 print_swizzle_vec4(word->swizzle, false, false);
1129
1130 printf(", ");
1131
1132 if (is_ubo) {
1133 printf("ubo%u", word->arg_1);
1134 update_stats(&midg_stats.uniform_buffer_count, word->arg_1);
1135 } else
1136 print_load_store_arg(word->arg_1, 0);
1137
1138 printf(", ");
1139 print_load_store_arg(word->arg_2, 1);
1140 printf(" /* %X */\n", word->varying_parameters);
1141
1142 midg_stats.instruction_count++;
1143 }
1144
1145 static void
1146 print_load_store_word(uint32_t *word, unsigned tabs)
1147 {
1148 midgard_load_store *load_store = (midgard_load_store *) word;
1149
1150 if (load_store->word1 != 3) {
1151 print_load_store_instr(load_store->word1, tabs);
1152 }
1153
1154 if (load_store->word2 != 3) {
1155 print_load_store_instr(load_store->word2, tabs);
1156 }
1157 }
1158
1159 static void
1160 print_texture_reg(bool full, bool select, bool upper)
1161 {
1162 if (full)
1163 printf("r%d", REG_TEX_BASE + select);
1164 else
1165 printf("hr%d", (REG_TEX_BASE + select) * 2 + upper);
1166
1167 if (full && upper)
1168 printf("// error: out full / upper mutually exclusive\n");
1169
1170 }
1171
1172 static void
1173 print_texture_reg_triple(unsigned triple)
1174 {
1175 bool full = triple & 1;
1176 bool select = triple & 2;
1177 bool upper = triple & 4;
1178
1179 print_texture_reg(full, select, upper);
1180 }
1181
1182 static void
1183 print_texture_reg_select(uint8_t u)
1184 {
1185 midgard_tex_register_select sel;
1186 memcpy(&sel, &u, sizeof(u));
1187
1188 if (!sel.full)
1189 printf("h");
1190
1191 printf("r%u", REG_TEX_BASE + sel.select);
1192
1193 unsigned component = sel.component;
1194
1195 /* Use the upper half in half-reg mode */
1196 if (sel.upper) {
1197 assert(!sel.full);
1198 component += 4;
1199 }
1200
1201 printf(".%c", components[component]);
1202
1203 assert(sel.zero == 0);
1204 }
1205
1206 static void
1207 print_texture_format(int format)
1208 {
1209 /* Act like a modifier */
1210 printf(".");
1211
1212 switch (format) {
1213 DEFINE_CASE(MALI_TEX_1D, "1d");
1214 DEFINE_CASE(MALI_TEX_2D, "2d");
1215 DEFINE_CASE(MALI_TEX_3D, "3d");
1216 DEFINE_CASE(MALI_TEX_CUBE, "cube");
1217
1218 default:
1219 unreachable("Bad format");
1220 }
1221 }
1222
1223 static bool
1224 midgard_op_has_helpers(unsigned op, bool gather)
1225 {
1226 if (gather)
1227 return true;
1228
1229 switch (op) {
1230 case TEXTURE_OP_NORMAL:
1231 case TEXTURE_OP_DFDX:
1232 case TEXTURE_OP_DFDY:
1233 return true;
1234 default:
1235 return false;
1236 }
1237 }
1238
1239 static void
1240 print_texture_op(unsigned op, bool gather)
1241 {
1242 /* Act like a bare name, like ESSL functions */
1243
1244 if (gather) {
1245 printf("textureGather");
1246
1247 unsigned component = op >> 4;
1248 unsigned bottom = op & 0xF;
1249
1250 if (bottom != 0x2)
1251 printf("_unk%u", bottom);
1252
1253 printf(".%c", components[component]);
1254 return;
1255 }
1256
1257 switch (op) {
1258 DEFINE_CASE(TEXTURE_OP_NORMAL, "texture");
1259 DEFINE_CASE(TEXTURE_OP_LOD, "textureLod");
1260 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH, "texelFetch");
1261 DEFINE_CASE(TEXTURE_OP_DFDX, "dFdx");
1262 DEFINE_CASE(TEXTURE_OP_DFDY, "dFdy");
1263
1264 default:
1265 printf("tex_%X", op);
1266 break;
1267 }
1268 }
1269
1270 static bool
1271 texture_op_takes_bias(unsigned op)
1272 {
1273 return op == TEXTURE_OP_NORMAL;
1274 }
1275
1276 static char
1277 sampler_type_name(enum mali_sampler_type t)
1278 {
1279 switch (t) {
1280 case MALI_SAMPLER_FLOAT:
1281 return 'f';
1282 case MALI_SAMPLER_UNSIGNED:
1283 return 'u';
1284 case MALI_SAMPLER_SIGNED:
1285 return 'i';
1286 default:
1287 return '?';
1288 }
1289
1290 }
1291
1292 #undef DEFINE_CASE
1293
1294 static void
1295 print_texture_word(uint32_t *word, unsigned tabs)
1296 {
1297 midgard_texture_word *texture = (midgard_texture_word *) word;
1298
1299 midg_stats.helper_invocations |=
1300 midgard_op_has_helpers(texture->op, texture->is_gather);
1301
1302 /* Broad category of texture operation in question */
1303 print_texture_op(texture->op, texture->is_gather);
1304
1305 /* Specific format in question */
1306 print_texture_format(texture->format);
1307
1308 /* Instruction "modifiers" parallel the ALU instructions. */
1309
1310 if (texture->shadow)
1311 printf(".shadow");
1312
1313 if (texture->cont)
1314 printf(".cont");
1315
1316 if (texture->last)
1317 printf(".last");
1318
1319 /* Output modifiers are always interpreted floatly */
1320 print_outmod(texture->outmod, false);
1321
1322 printf(" ");
1323
1324 print_texture_reg(texture->out_full, texture->out_reg_select, texture->out_upper);
1325 print_mask_4(texture->mask);
1326 printf(", ");
1327
1328 /* Depending on whether we read from textures directly or indirectly,
1329 * we may be able to update our analysis */
1330
1331 if (texture->texture_register) {
1332 printf("texture[");
1333 print_texture_reg_select(texture->texture_handle);
1334 printf("], ");
1335
1336 /* Indirect, tut tut */
1337 midg_stats.texture_count = -16;
1338 } else {
1339 printf("texture%u, ", texture->texture_handle);
1340 update_stats(&midg_stats.texture_count, texture->texture_handle);
1341 }
1342
1343 /* Print the type, GL style */
1344 printf("%csampler", sampler_type_name(texture->sampler_type));
1345
1346 if (texture->sampler_register) {
1347 printf("[");
1348 print_texture_reg_select(texture->sampler_handle);
1349 printf("]");
1350
1351 midg_stats.sampler_count = -16;
1352 } else {
1353 printf("%u", texture->sampler_handle);
1354 update_stats(&midg_stats.sampler_count, texture->sampler_handle);
1355 }
1356
1357 print_swizzle_vec4(texture->swizzle, false, false);
1358 printf(", ");
1359
1360 print_texture_reg(texture->in_reg_full, texture->in_reg_select, texture->in_reg_upper);
1361 print_swizzle_vec4(texture->in_reg_swizzle, false, false);
1362
1363 /* There is *always* an offset attached. Of
1364 * course, that offset is just immediate #0 for a
1365 * GLES call that doesn't take an offset. If there
1366 * is a non-negative non-zero offset, this is
1367 * specified in immediate offset mode, with the
1368 * values in the offset_* fields as immediates. If
1369 * this is a negative offset, we instead switch to
1370 * a register offset mode, where the offset_*
1371 * fields become register triplets */
1372
1373 if (texture->offset_register) {
1374 printf(" + ");
1375 print_texture_reg_triple(texture->offset_x);
1376
1377 /* The less questions you ask, the better. */
1378
1379 unsigned swizzle_lo, swizzle_hi;
1380 unsigned orig_y = texture->offset_y;
1381 unsigned orig_z = texture->offset_z;
1382
1383 memcpy(&swizzle_lo, &orig_y, sizeof(unsigned));
1384 memcpy(&swizzle_hi, &orig_z, sizeof(unsigned));
1385
1386 /* Duplicate hi swizzle over */
1387 assert(swizzle_hi < 4);
1388 swizzle_hi = (swizzle_hi << 2) | swizzle_hi;
1389
1390 unsigned swiz = (swizzle_lo << 4) | swizzle_hi;
1391 unsigned reversed = util_bitreverse(swiz) >> 24;
1392 print_swizzle_vec4(reversed, false, false);
1393
1394 printf(", ");
1395 } else if (texture->offset_x || texture->offset_y || texture->offset_z) {
1396 /* Only select ops allow negative immediate offsets, verify */
1397
1398 bool neg_x = texture->offset_x < 0;
1399 bool neg_y = texture->offset_y < 0;
1400 bool neg_z = texture->offset_z < 0;
1401 bool any_neg = neg_x || neg_y || neg_z;
1402
1403 if (any_neg && texture->op != TEXTURE_OP_TEXEL_FETCH)
1404 printf("/* invalid negative */ ");
1405
1406 /* Regardless, just print the immediate offset */
1407
1408 printf(" + <%d, %d, %d>, ",
1409 texture->offset_x,
1410 texture->offset_y,
1411 texture->offset_z);
1412 } else {
1413 printf(", ");
1414 }
1415
1416 char lod_operand = texture_op_takes_bias(texture->op) ? '+' : '=';
1417
1418 if (texture->lod_register) {
1419 printf("lod %c ", lod_operand);
1420 print_texture_reg_select(texture->bias);
1421 printf(", ");
1422
1423 if (texture->bias_int)
1424 printf(" /* bias_int = 0x%X */", texture->bias_int);
1425 } else if (texture->op == TEXTURE_OP_TEXEL_FETCH) {
1426 /* For texel fetch, the int LOD is in the fractional place and
1427 * there is no fraction / possibility of bias. We *always* have
1428 * an explicit LOD, even if it's zero. */
1429
1430 if (texture->bias_int)
1431 printf(" /* bias_int = 0x%X */ ", texture->bias_int);
1432
1433 printf("lod = %u, ", texture->bias);
1434 } else if (texture->bias || texture->bias_int) {
1435 signed bias_int = texture->bias_int;
1436 float bias_frac = texture->bias / 256.0f;
1437 float bias = bias_int + bias_frac;
1438
1439 bool is_bias = texture_op_takes_bias(texture->op);
1440 char sign = (bias >= 0.0) ? '+' : '-';
1441 char operand = is_bias ? sign : '=';
1442
1443 printf("lod %c %f, ", operand, fabsf(bias));
1444 }
1445
1446 printf("\n");
1447
1448 /* While not zero in general, for these simple instructions the
1449 * following unknowns are zero, so we don't include them */
1450
1451 if (texture->unknown4 ||
1452 texture->unknownA ||
1453 texture->unknown8) {
1454 printf("// unknown4 = 0x%x\n", texture->unknown4);
1455 printf("// unknownA = 0x%x\n", texture->unknownA);
1456 printf("// unknown8 = 0x%x\n", texture->unknown8);
1457 }
1458
1459 midg_stats.instruction_count++;
1460 }
1461
1462 struct midgard_disasm_stats
1463 disassemble_midgard(uint8_t *code, size_t size)
1464 {
1465 uint32_t *words = (uint32_t *) code;
1466 unsigned num_words = size / 4;
1467 int tabs = 0;
1468
1469 bool prefetch_flag = false;
1470
1471 int last_next_tag = -1;
1472
1473 unsigned i = 0;
1474
1475 /* Stats for shader-db */
1476 memset(&midg_stats, 0, sizeof(midg_stats));
1477 midg_ever_written = 0;
1478
1479 while (i < num_words) {
1480 unsigned tag = words[i] & 0xF;
1481 unsigned next_tag = (words[i] >> 4) & 0xF;
1482 unsigned num_quad_words = midgard_word_size[tag];
1483
1484 /* Check the tag */
1485 if (last_next_tag > 1) {
1486 if (last_next_tag != tag) {
1487 printf("/* TAG ERROR got ");
1488 print_tag_short(tag);
1489 printf(" expected ");
1490 print_tag_short(last_next_tag);
1491 printf(" */ ");
1492 }
1493 } else {
1494 /* TODO: Check ALU case */
1495 }
1496
1497 last_next_tag = next_tag;
1498
1499 switch (midgard_word_types[tag]) {
1500 case midgard_word_type_texture:
1501 print_texture_word(&words[i], tabs);
1502 break;
1503
1504 case midgard_word_type_load_store:
1505 print_load_store_word(&words[i], tabs);
1506 break;
1507
1508 case midgard_word_type_alu:
1509 print_alu_word(&words[i], num_quad_words, tabs);
1510
1511 /* Reset word static analysis state */
1512 is_embedded_constant_half = false;
1513 is_embedded_constant_int = false;
1514
1515 break;
1516
1517 default:
1518 printf("Unknown word type %u:\n", words[i] & 0xF);
1519 num_quad_words = 1;
1520 print_quad_word(&words[i], tabs);
1521 printf("\n");
1522 break;
1523 }
1524
1525 if (prefetch_flag && midgard_word_types[tag] == midgard_word_type_alu)
1526 break;
1527
1528 printf("\n");
1529
1530 unsigned next = (words[i] & 0xF0) >> 4;
1531
1532 /* We are parsing per bundle anyway */
1533 midg_stats.bundle_count++;
1534 midg_stats.quadword_count += num_quad_words;
1535
1536 /* Break based on instruction prefetch flag */
1537
1538 if (i < num_words && next == 1) {
1539 prefetch_flag = true;
1540
1541 if (midgard_word_types[words[i] & 0xF] != midgard_word_type_alu)
1542 break;
1543 }
1544
1545 i += 4 * num_quad_words;
1546 }
1547
1548 /* We computed work_count as max_work_registers, so add one to get the
1549 * count. If no work registers are written, you still have one work
1550 * reported, which is exactly what the hardware expects */
1551
1552 midg_stats.work_count++;
1553
1554 return midg_stats;
1555 }