5 * Copyright (c) 2013 Connor Abbott (connor@abbott.cx)
6 * Copyright (c) 2018 Alyssa Rosenzweig (alyssa@rosenzweig.io)
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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
33 #include "midgard-parse.h"
34 #include "disassemble.h"
35 #include "util/half_float.h"
37 #define DEFINE_CASE(define, str) case define: { printf(str); break; }
39 static bool is_instruction_int
= false;
42 print_alu_opcode(midgard_alu_op op
)
46 if (alu_opcode_names
[op
]) {
47 printf("%s", alu_opcode_names
[op
]);
49 int_op
= alu_opcode_names
[op
][0] == 'i';
51 printf("alu_op_%02X", op
);
53 /* For constant analysis */
54 is_instruction_int
= int_op
;
58 print_ld_st_opcode(midgard_load_store_op op
)
60 if (load_store_opcode_names
[op
])
61 printf("%s", load_store_opcode_names
[op
]);
63 printf("ldst_op_%02X", op
);
66 static bool is_embedded_constant_half
= false;
67 static bool is_embedded_constant_int
= false;
70 print_reg(unsigned reg
, bool half
)
72 /* Perform basic static analysis for expanding constants correctly */
74 if (half
&& (reg
>> 1) == 26) {
75 is_embedded_constant_half
= true;
76 is_embedded_constant_int
= is_instruction_int
;
77 } else if (!half
&& reg
== 26) {
78 is_embedded_constant_int
= is_instruction_int
;
87 static char *outmod_names
[4] = {
95 print_outmod(midgard_outmod outmod
)
97 printf("%s", outmod_names
[outmod
]);
101 print_quad_word(uint32_t *words
, unsigned tabs
)
105 for (i
= 0; i
< 4; i
++)
106 printf("0x%08X%s ", words
[i
], i
== 3 ? "" : ",");
112 print_vector_src(unsigned src_binary
, bool out_high
,
113 bool out_half
, unsigned reg
)
115 midgard_vector_alu_src
*src
= (midgard_vector_alu_src
*)&src_binary
;
127 printf(" /* half */ ");
135 half_reg
= reg
* 2 + 1;
138 printf(" /* rep_high */ ");
141 half_reg
= reg
* 2 + 1;
146 printf(" /* rep_low */ ");
149 print_reg(half_reg
, true);
152 printf(" /* rep_high */ ");
155 print_reg(reg
* 2 + src
->rep_low
, true);
158 printf(" /* rep_low */ ");
160 print_reg(reg
, false);
166 if (src
->swizzle
!= 0xE4) { //default swizzle
168 static const char c
[4] = "xyzw";
172 for (i
= 0; i
< 4; i
++)
173 printf("%c", c
[(src
->swizzle
>> (i
* 2)) & 3]);
181 decode_vector_imm(unsigned src2_reg
, unsigned imm
)
184 ret
= src2_reg
<< 11;
185 ret
|= (imm
& 0x7) << 8;
186 ret
|= (imm
>> 3) & 0xFF;
191 print_immediate(uint16_t imm
)
193 if (is_instruction_int
)
196 printf("#%g", _mesa_half_to_float(imm
));
200 print_vector_field(const char *name
, uint16_t *words
, uint16_t reg_word
,
203 midgard_reg_info
*reg_info
= (midgard_reg_info
*)®_word
;
204 midgard_vector_alu
*alu_field
= (midgard_vector_alu
*) words
;
206 if (alu_field
->reg_mode
!= midgard_reg_mode_half
&&
207 alu_field
->reg_mode
!= midgard_reg_mode_full
) {
208 printf("unknown reg mode %u\n", alu_field
->reg_mode
);
211 /* For now, prefix instruction names with their unit, until we
212 * understand how this works on a deeper level */
215 print_alu_opcode(alu_field
->op
);
216 print_outmod(alu_field
->outmod
);
219 bool half
, out_half
, out_high
= false;
222 half
= (alu_field
->reg_mode
== midgard_reg_mode_half
);
225 if (alu_field
->mask
& 0xF) {
228 if ((alu_field
->mask
& 0xF0))
229 printf("/* %X */ ", alu_field
->mask
);
231 mask
= alu_field
->mask
;
234 mask
= alu_field
->mask
>> 4;
237 mask
= alu_field
->mask
& 1;
238 mask
|= (alu_field
->mask
& 4) >> 1;
239 mask
|= (alu_field
->mask
& 16) >> 2;
240 mask
|= (alu_field
->mask
& 64) >> 3;
245 if (alu_field
->dest_override
!= midgard_dest_override_none
) {
247 printf("/* half */ ");
251 if (alu_field
->dest_override
== midgard_dest_override_lower
)
253 else if (alu_field
->dest_override
== midgard_dest_override_upper
)
261 print_reg(2 * reg_info
->out_reg
+ 1, true);
263 print_reg(2 * reg_info
->out_reg
, true);
265 print_reg(reg_info
->out_reg
, false);
269 static const char c
[4] = "xyzw";
273 for (i
= 0; i
< 4; i
++)
280 print_vector_src(alu_field
->src1
, out_high
, half
, reg_info
->src1_reg
);
284 if (reg_info
->src2_imm
) {
285 uint16_t imm
= decode_vector_imm(reg_info
->src2_reg
, alu_field
->src2
>> 2);
286 print_immediate(imm
);
288 print_vector_src(alu_field
->src2
, out_high
, half
,
296 print_scalar_src(unsigned src_binary
, unsigned reg
)
298 midgard_scalar_alu_src
*src
= (midgard_scalar_alu_src
*)&src_binary
;
307 print_reg(reg
, false);
309 print_reg(reg
* 2 + (src
->component
>> 2), true);
311 static const char c
[4] = "xyzw";
313 printf(".%c", c
[src
->full
? src
->component
>> 1 : src
->component
& 3]);
321 decode_scalar_imm(unsigned src2_reg
, unsigned imm
)
324 ret
= src2_reg
<< 11;
325 ret
|= (imm
& 3) << 9;
326 ret
|= (imm
& 4) << 6;
327 ret
|= (imm
& 0x38) << 2;
333 print_scalar_field(const char *name
, uint16_t *words
, uint16_t reg_word
,
336 midgard_reg_info
*reg_info
= (midgard_reg_info
*)®_word
;
337 midgard_scalar_alu
*alu_field
= (midgard_scalar_alu
*) words
;
339 if (alu_field
->unknown
)
340 printf("scalar ALU unknown bit set\n");
343 print_alu_opcode(alu_field
->op
);
344 print_outmod(alu_field
->outmod
);
347 if (alu_field
->output_full
)
348 print_reg(reg_info
->out_reg
, false);
350 print_reg(reg_info
->out_reg
* 2 + (alu_field
->output_component
>> 2),
353 static const char c
[4] = "xyzw";
355 c
[alu_field
->output_full
? alu_field
->output_component
>> 1 :
356 alu_field
->output_component
& 3]);
358 print_scalar_src(alu_field
->src1
, reg_info
->src1_reg
);
362 if (reg_info
->src2_imm
) {
363 uint16_t imm
= decode_scalar_imm(reg_info
->src2_reg
,
365 print_immediate(imm
);
367 print_scalar_src(alu_field
->src2
, reg_info
->src2_reg
);
373 print_branch_op(int op
)
376 case midgard_jmp_writeout_op_branch_uncond
:
380 case midgard_jmp_writeout_op_branch_cond
:
384 case midgard_jmp_writeout_op_writeout
:
388 case midgard_jmp_writeout_op_discard
:
393 printf("unk%d.", op
);
399 print_branch_cond(int cond
)
402 case midgard_condition_write0
:
406 case midgard_condition_false
:
410 case midgard_condition_true
:
414 case midgard_condition_always
:
419 printf("unk%X", cond
);
425 print_compact_branch_writeout_field(uint16_t word
)
427 midgard_jmp_writeout_op op
= word
& 0x7;
430 case midgard_jmp_writeout_op_branch_uncond
: {
431 midgard_branch_uncond br_uncond
;
432 memcpy((char *) &br_uncond
, (char *) &word
, sizeof(br_uncond
));
433 printf("br.uncond ");
435 if (br_uncond
.unknown
!= 1)
436 printf("unknown:%d, ", br_uncond
.unknown
);
438 if (br_uncond
.offset
>= 0)
441 printf("%d", br_uncond
.offset
);
443 printf(" -> %X\n", br_uncond
.dest_tag
);
447 case midgard_jmp_writeout_op_branch_cond
:
448 case midgard_jmp_writeout_op_writeout
:
449 case midgard_jmp_writeout_op_discard
:
451 midgard_branch_cond br_cond
;
452 memcpy((char *) &br_cond
, (char *) &word
, sizeof(br_cond
));
456 print_branch_op(br_cond
.op
);
457 print_branch_cond(br_cond
.cond
);
461 if (br_cond
.offset
>= 0)
464 printf("%d", br_cond
.offset
);
466 printf(" -> %X\n", br_cond
.dest_tag
);
473 print_extended_branch_writeout_field(uint8_t *words
)
475 midgard_branch_extended br
;
476 memcpy((char *) &br
, (char *) words
, sizeof(br
));
480 print_branch_op(br
.op
);
482 /* Condition repeated 8 times in all known cases. Check this. */
484 unsigned cond
= br
.cond
& 0x3;
486 for (unsigned i
= 0; i
< 16; i
+= 2) {
487 assert(((br
.cond
>> i
) & 0x3) == cond
);
490 print_branch_cond(cond
);
493 printf(".unknown%d", br
.unknown
);
500 printf("%d", br
.offset
);
502 printf(" -> %X\n", br
.dest_tag
);
506 num_alu_fields_enabled(uint32_t control_word
)
510 if ((control_word
>> 17) & 1)
513 if ((control_word
>> 19) & 1)
516 if ((control_word
>> 21) & 1)
519 if ((control_word
>> 23) & 1)
522 if ((control_word
>> 25) & 1)
529 float_bitcast(uint32_t integer
)
541 print_alu_word(uint32_t *words
, unsigned num_quad_words
,
544 uint32_t control_word
= words
[0];
545 uint16_t *beginning_ptr
= (uint16_t *)(words
+ 1);
546 unsigned num_fields
= num_alu_fields_enabled(control_word
);
547 uint16_t *word_ptr
= beginning_ptr
+ num_fields
;
548 unsigned num_words
= 2 + num_fields
;
550 if ((control_word
>> 16) & 1)
551 printf("unknown bit 16 enabled\n");
553 if ((control_word
>> 17) & 1) {
554 print_vector_field("vmul", word_ptr
, *beginning_ptr
, tabs
);
560 if ((control_word
>> 18) & 1)
561 printf("unknown bit 18 enabled\n");
563 if ((control_word
>> 19) & 1) {
564 print_scalar_field("sadd", word_ptr
, *beginning_ptr
, tabs
);
570 if ((control_word
>> 20) & 1)
571 printf("unknown bit 20 enabled\n");
573 if ((control_word
>> 21) & 1) {
574 print_vector_field("vadd", word_ptr
, *beginning_ptr
, tabs
);
580 if ((control_word
>> 22) & 1)
581 printf("unknown bit 22 enabled\n");
583 if ((control_word
>> 23) & 1) {
584 print_scalar_field("smul", word_ptr
, *beginning_ptr
, tabs
);
590 if ((control_word
>> 24) & 1)
591 printf("unknown bit 24 enabled\n");
593 if ((control_word
>> 25) & 1) {
594 print_vector_field("lut", word_ptr
, *beginning_ptr
, tabs
);
600 if ((control_word
>> 26) & 1) {
601 print_compact_branch_writeout_field(*word_ptr
);
606 if ((control_word
>> 27) & 1) {
607 print_extended_branch_writeout_field((uint8_t *) word_ptr
);
612 if (num_quad_words
> (num_words
+ 7) / 8) {
613 assert(num_quad_words
== (num_words
+ 15) / 8);
614 //Assume that the extra quadword is constants
615 void *consts
= words
+ (4 * num_quad_words
- 4);
617 if (is_embedded_constant_int
) {
618 if (is_embedded_constant_half
) {
619 int16_t *sconsts
= (int16_t *) consts
;
620 printf("sconstants %d, %d, %d, %d\n",
626 int32_t *iconsts
= (int32_t *) consts
;
627 printf("iconstants %d, %d, %d, %d\n",
634 if (is_embedded_constant_half
) {
635 uint16_t *hconsts
= (uint16_t *) consts
;
636 printf("hconstants %g, %g, %g, %g\n",
637 _mesa_half_to_float(hconsts
[0]),
638 _mesa_half_to_float(hconsts
[1]),
639 _mesa_half_to_float(hconsts
[2]),
640 _mesa_half_to_float(hconsts
[3]));
642 uint32_t *fconsts
= (uint32_t *) consts
;
643 printf("fconstants %g, %g, %g, %g\n",
644 float_bitcast(fconsts
[0]),
645 float_bitcast(fconsts
[1]),
646 float_bitcast(fconsts
[2]),
647 float_bitcast(fconsts
[3]));
654 /* Swizzle/mask formats are common between load/store ops and texture ops, it
658 print_swizzle(uint32_t swizzle
)
662 if (swizzle
!= 0xE4) {
665 for (i
= 0; i
< 4; i
++)
666 printf("%c", "xyzw"[(swizzle
>> (2 * i
)) & 3]);
671 print_mask(uint32_t mask
)
678 for (i
= 0; i
< 4; i
++)
680 printf("%c", "xyzw"[i
]);
682 /* Handle degenerate case */
689 print_varying_parameters(midgard_load_store_word
*word
)
691 midgard_varying_parameter param
;
692 unsigned v
= word
->varying_parameters
;
693 memcpy(¶m
, &v
, sizeof(param
));
695 if (param
.is_varying
) {
696 /* If a varying, there are qualifiers */
700 if (param
.interpolation
!= midgard_interp_default
) {
701 if (param
.interpolation
== midgard_interp_centroid
)
704 printf(".interp%d", param
.interpolation
);
706 } else if (param
.flat
|| param
.interpolation
) {
707 printf(" /* is_varying not set but varying metadata attached */");
710 if (param
.zero1
|| param
.zero2
)
711 printf(" /* zero tripped, %d %d */ ", param
.zero1
, param
.zero2
);
715 is_op_varying(unsigned op
)
718 case midgard_op_store_vary_16
:
719 case midgard_op_store_vary_32
:
720 case midgard_op_load_vary_16
:
721 case midgard_op_load_vary_32
:
729 print_load_store_instr(uint64_t data
,
732 midgard_load_store_word
*word
= (midgard_load_store_word
*) &data
;
734 print_ld_st_opcode(word
->op
);
736 if (is_op_varying(word
->op
))
737 print_varying_parameters(word
);
739 printf(" r%d", word
->reg
);
740 print_mask(word
->mask
);
742 int address
= word
->address
;
744 if (word
->op
== midgard_op_load_uniform_32
) {
745 /* Uniforms use their own addressing scheme */
747 int lo
= word
->varying_parameters
>> 7;
748 int hi
= word
->address
;
750 /* TODO: Combine fields logically */
751 address
= (hi
<< 3) | lo
;
754 printf(", %d", address
);
756 print_swizzle(word
->swizzle
);
758 printf(", 0x%X\n", word
->unknown
);
762 print_load_store_word(uint32_t *word
, unsigned tabs
)
764 midgard_load_store
*load_store
= (midgard_load_store
*) word
;
766 if (load_store
->word1
!= 3) {
767 print_load_store_instr(load_store
->word1
, tabs
);
770 if (load_store
->word2
!= 3) {
771 print_load_store_instr(load_store
->word2
, tabs
);
776 print_texture_reg(bool full
, bool select
, bool upper
)
779 printf("r%d", REG_TEX_BASE
+ select
);
781 printf("hr%d", (REG_TEX_BASE
+ select
) * 2 + upper
);
784 printf("// error: out full / upper mutually exclusive\n");
789 print_texture_format(int format
)
791 /* Act like a modifier */
795 DEFINE_CASE(TEXTURE_2D
, "2d");
796 DEFINE_CASE(TEXTURE_3D
, "3d");
799 printf("fmt_%d", format
);
805 print_texture_op(int format
)
807 /* Act like a modifier */
811 DEFINE_CASE(TEXTURE_OP_NORMAL
, "normal");
812 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH
, "texelfetch");
815 printf("op_%d", format
);
823 print_texture_word(uint32_t *word
, unsigned tabs
)
825 midgard_texture_word
*texture
= (midgard_texture_word
*) word
;
827 /* Instruction family, like ALU words have theirs */
830 /* Broad category of texture operation in question */
831 print_texture_op(texture
->op
);
833 /* Specific format in question */
834 print_texture_format(texture
->format
);
836 /* Instruction "modifiers" parallel the ALU instructions. First group
837 * are modifiers that act alone */
839 if (!texture
->filter
)
851 /* Second set are modifiers which take an extra argument each */
853 if (texture
->has_offset
)
861 print_texture_reg(texture
->out_full
, texture
->out_reg_select
, texture
->out_upper
);
862 print_mask(texture
->mask
);
865 printf("texture%d, ", texture
->texture_handle
);
867 printf("sampler%d", texture
->sampler_handle
);
868 print_swizzle(texture
->swizzle
);
871 print_texture_reg(/*texture->in_reg_full*/true, texture
->in_reg_select
, texture
->in_reg_upper
);
872 printf(".%c%c, ", "xyzw"[texture
->in_reg_swizzle_left
],
873 "xyzw"[texture
->in_reg_swizzle_right
]);
875 /* TODO: can offsets be full words? */
876 if (texture
->has_offset
) {
877 print_texture_reg(false, texture
->offset_reg_select
, texture
->offset_reg_upper
);
882 printf("%f, ", texture
->bias
/ 256.0f
);
886 /* While not zero in general, for these simple instructions the
887 * following unknowns are zero, so we don't include them */
889 if (texture
->unknown1
||
897 printf("// unknown1 = 0x%x\n", texture
->unknown1
);
898 printf("// unknown2 = 0x%x\n", texture
->unknown2
);
899 printf("// unknown3 = 0x%x\n", texture
->unknown3
);
900 printf("// unknown4 = 0x%x\n", texture
->unknown4
);
901 printf("// unknownA = 0x%x\n", texture
->unknownA
);
902 printf("// unknownB = 0x%x\n", texture
->unknownB
);
903 printf("// unknown8 = 0x%x\n", texture
->unknown8
);
904 printf("// unknown9 = 0x%x\n", texture
->unknown9
);
907 /* Similarly, if no offset is applied, these are zero. If an offset
908 * -is- applied, or gradients are used, etc, these are nonzero but
909 * largely unknown still. */
911 if (texture
->offset_unknown1
||
912 texture
->offset_reg_select
||
913 texture
->offset_reg_upper
||
914 texture
->offset_unknown4
||
915 texture
->offset_unknown5
||
916 texture
->offset_unknown6
||
917 texture
->offset_unknown7
||
918 texture
->offset_unknown8
||
919 texture
->offset_unknown9
) {
920 printf("// offset_unknown1 = 0x%x\n", texture
->offset_unknown1
);
921 printf("// offset_reg_select = 0x%x\n", texture
->offset_reg_select
);
922 printf("// offset_reg_upper = 0x%x\n", texture
->offset_reg_upper
);
923 printf("// offset_unknown4 = 0x%x\n", texture
->offset_unknown4
);
924 printf("// offset_unknown5 = 0x%x\n", texture
->offset_unknown5
);
925 printf("// offset_unknown6 = 0x%x\n", texture
->offset_unknown6
);
926 printf("// offset_unknown7 = 0x%x\n", texture
->offset_unknown7
);
927 printf("// offset_unknown8 = 0x%x\n", texture
->offset_unknown8
);
928 printf("// offset_unknown9 = 0x%x\n", texture
->offset_unknown9
);
932 if (texture
->unknown7
!= 0x1)
933 printf("// (!) unknown7 = %d\n", texture
->unknown7
);
937 disassemble_midgard(uint8_t *code
, size_t size
)
939 uint32_t *words
= (uint32_t *) code
;
940 unsigned num_words
= size
/ 4;
943 bool prefetch_flag
= false;
947 while (i
< num_words
) {
948 unsigned num_quad_words
= midgard_word_size
[words
[i
] & 0xF];
950 switch (midgard_word_types
[words
[i
] & 0xF]) {
951 case midgard_word_type_texture
:
952 print_texture_word(&words
[i
], tabs
);
955 case midgard_word_type_load_store
:
956 print_load_store_word(&words
[i
], tabs
);
959 case midgard_word_type_alu
:
960 print_alu_word(&words
[i
], num_quad_words
, tabs
);
965 /* Reset word static analysis state */
966 is_embedded_constant_half
= false;
967 is_embedded_constant_int
= false;
972 printf("Unknown word type %u:\n", words
[i
] & 0xF);
974 print_quad_word(&words
[i
], tabs
);
981 unsigned next
= (words
[i
] & 0xF0) >> 4;
983 i
+= 4 * num_quad_words
;
985 /* Break based on instruction prefetch flag */
987 if (i
< num_words
&& next
== 1) {
988 prefetch_flag
= true;
990 if (midgard_word_types
[words
[i
] & 0xF] != midgard_word_type_alu
)