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_cond
:
380 case midgard_jmp_writeout_op_writeout
:
384 case midgard_jmp_writeout_op_discard
:
389 printf("unk%d.", op
);
395 print_branch_cond(int cond
)
398 case midgard_condition_write0
:
402 case midgard_condition_false
:
406 case midgard_condition_true
:
410 case midgard_condition_always
:
420 print_compact_branch_writeout_field(uint16_t word
)
422 midgard_jmp_writeout_op op
= word
& 0x7;
425 case midgard_jmp_writeout_op_branch_uncond
: {
426 midgard_branch_uncond br_uncond
;
427 memcpy((char *) &br_uncond
, (char *) &word
, sizeof(br_uncond
));
428 printf("br.uncond ");
430 if (br_uncond
.unknown
!= 1)
431 printf("unknown:%d, ", br_uncond
.unknown
);
433 if (br_uncond
.offset
>= 0)
436 printf("%d", br_uncond
.offset
);
438 printf(" -> %X\n", br_uncond
.dest_tag
);
442 case midgard_jmp_writeout_op_branch_cond
:
443 case midgard_jmp_writeout_op_writeout
:
444 case midgard_jmp_writeout_op_discard
:
446 midgard_branch_cond br_cond
;
447 memcpy((char *) &br_cond
, (char *) &word
, sizeof(br_cond
));
451 print_branch_op(br_cond
.op
);
452 print_branch_cond(br_cond
.cond
);
456 if (br_cond
.offset
>= 0)
459 printf("%d", br_cond
.offset
);
461 printf(" -> %X\n", br_cond
.dest_tag
);
468 print_extended_branch_writeout_field(uint8_t *words
)
470 midgard_branch_extended br
;
471 memcpy((char *) &br
, (char *) words
, sizeof(br
));
475 print_branch_op(br
.op
);
476 print_branch_cond(br
.cond
);
478 /* XXX: This can't be right */
480 printf(".unknown%d\n", br
.unknown
);
483 printf(".zero%d\n", br
.zero
);
490 printf("%d", br
.offset
);
492 printf(" -> %X\n", br
.dest_tag
);
496 num_alu_fields_enabled(uint32_t control_word
)
500 if ((control_word
>> 17) & 1)
503 if ((control_word
>> 19) & 1)
506 if ((control_word
>> 21) & 1)
509 if ((control_word
>> 23) & 1)
512 if ((control_word
>> 25) & 1)
519 float_bitcast(uint32_t integer
)
531 print_alu_word(uint32_t *words
, unsigned num_quad_words
,
534 uint32_t control_word
= words
[0];
535 uint16_t *beginning_ptr
= (uint16_t *)(words
+ 1);
536 unsigned num_fields
= num_alu_fields_enabled(control_word
);
537 uint16_t *word_ptr
= beginning_ptr
+ num_fields
;
538 unsigned num_words
= 2 + num_fields
;
540 if ((control_word
>> 16) & 1)
541 printf("unknown bit 16 enabled\n");
543 if ((control_word
>> 17) & 1) {
544 print_vector_field("vmul", word_ptr
, *beginning_ptr
, tabs
);
550 if ((control_word
>> 18) & 1)
551 printf("unknown bit 18 enabled\n");
553 if ((control_word
>> 19) & 1) {
554 print_scalar_field("sadd", word_ptr
, *beginning_ptr
, tabs
);
560 if ((control_word
>> 20) & 1)
561 printf("unknown bit 20 enabled\n");
563 if ((control_word
>> 21) & 1) {
564 print_vector_field("vadd", word_ptr
, *beginning_ptr
, tabs
);
570 if ((control_word
>> 22) & 1)
571 printf("unknown bit 22 enabled\n");
573 if ((control_word
>> 23) & 1) {
574 print_scalar_field("smul", word_ptr
, *beginning_ptr
, tabs
);
580 if ((control_word
>> 24) & 1)
581 printf("unknown bit 24 enabled\n");
583 if ((control_word
>> 25) & 1) {
584 print_vector_field("lut", word_ptr
, *beginning_ptr
, tabs
);
590 if ((control_word
>> 26) & 1) {
591 print_compact_branch_writeout_field(*word_ptr
);
596 if ((control_word
>> 27) & 1) {
597 print_extended_branch_writeout_field((uint8_t *) word_ptr
);
602 if (num_quad_words
> (num_words
+ 7) / 8) {
603 assert(num_quad_words
== (num_words
+ 15) / 8);
604 //Assume that the extra quadword is constants
605 void *consts
= words
+ (4 * num_quad_words
- 4);
607 if (is_embedded_constant_int
) {
608 if (is_embedded_constant_half
) {
609 int16_t *sconsts
= (int16_t *) consts
;
610 printf("sconstants %d, %d, %d, %d\n",
616 int32_t *iconsts
= (int32_t *) consts
;
617 printf("iconstants %d, %d, %d, %d\n",
624 if (is_embedded_constant_half
) {
625 uint16_t *hconsts
= (uint16_t *) consts
;
626 printf("hconstants %g, %g, %g, %g\n",
627 _mesa_half_to_float(hconsts
[0]),
628 _mesa_half_to_float(hconsts
[1]),
629 _mesa_half_to_float(hconsts
[2]),
630 _mesa_half_to_float(hconsts
[3]));
632 uint32_t *fconsts
= (uint32_t *) consts
;
633 printf("fconstants %g, %g, %g, %g\n",
634 float_bitcast(fconsts
[0]),
635 float_bitcast(fconsts
[1]),
636 float_bitcast(fconsts
[2]),
637 float_bitcast(fconsts
[3]));
644 /* Swizzle/mask formats are common between load/store ops and texture ops, it
648 print_swizzle(uint32_t swizzle
)
652 if (swizzle
!= 0xE4) {
655 for (i
= 0; i
< 4; i
++)
656 printf("%c", "xyzw"[(swizzle
>> (2 * i
)) & 3]);
661 print_mask(uint32_t mask
)
668 for (i
= 0; i
< 4; i
++)
670 printf("%c", "xyzw"[i
]);
672 /* Handle degenerate case */
679 print_varying_parameters(midgard_load_store_word
*word
)
681 midgard_varying_parameter param
;
682 unsigned v
= word
->varying_parameters
;
683 memcpy(¶m
, &v
, sizeof(param
));
685 if (param
.is_varying
) {
686 /* If a varying, there are qualifiers */
690 if (param
.interpolation
!= midgard_interp_default
) {
691 if (param
.interpolation
== midgard_interp_centroid
)
694 printf(".interp%d", param
.interpolation
);
696 } else if (param
.flat
|| param
.interpolation
) {
697 printf(" /* is_varying not set but varying metadata attached */");
700 if (param
.zero1
|| param
.zero2
)
701 printf(" /* zero tripped, %d %d */ ", param
.zero1
, param
.zero2
);
705 is_op_varying(unsigned op
)
708 case midgard_op_store_vary_16
:
709 case midgard_op_store_vary_32
:
710 case midgard_op_load_vary_16
:
711 case midgard_op_load_vary_32
:
719 print_load_store_instr(uint64_t data
,
722 midgard_load_store_word
*word
= (midgard_load_store_word
*) &data
;
724 print_ld_st_opcode(word
->op
);
726 if (is_op_varying(word
->op
))
727 print_varying_parameters(word
);
729 printf(" r%d", word
->reg
);
730 print_mask(word
->mask
);
732 int address
= word
->address
;
734 if (word
->op
== midgard_op_load_uniform_32
) {
735 /* Uniforms use their own addressing scheme */
737 int lo
= word
->varying_parameters
>> 7;
738 int hi
= word
->address
;
740 /* TODO: Combine fields logically */
741 address
= (hi
<< 3) | lo
;
744 printf(", %d", address
);
746 print_swizzle(word
->swizzle
);
748 printf(", 0x%X\n", word
->unknown
);
752 print_load_store_word(uint32_t *word
, unsigned tabs
)
754 midgard_load_store
*load_store
= (midgard_load_store
*) word
;
756 if (load_store
->word1
!= 3) {
757 print_load_store_instr(load_store
->word1
, tabs
);
760 if (load_store
->word2
!= 3) {
761 print_load_store_instr(load_store
->word2
, tabs
);
766 print_texture_reg(bool full
, bool select
, bool upper
)
769 printf("r%d", REG_TEX_BASE
+ select
);
771 printf("hr%d", (REG_TEX_BASE
+ select
) * 2 + upper
);
774 printf("// error: out full / upper mutually exclusive\n");
779 print_texture_format(int format
)
781 /* Act like a modifier */
785 DEFINE_CASE(TEXTURE_2D
, "2d");
786 DEFINE_CASE(TEXTURE_3D
, "3d");
789 printf("fmt_%d", format
);
795 print_texture_op(int format
)
797 /* Act like a modifier */
801 DEFINE_CASE(TEXTURE_OP_NORMAL
, "normal");
802 DEFINE_CASE(TEXTURE_OP_TEXEL_FETCH
, "texelfetch");
805 printf("op_%d", format
);
813 print_texture_word(uint32_t *word
, unsigned tabs
)
815 midgard_texture_word
*texture
= (midgard_texture_word
*) word
;
817 /* Instruction family, like ALU words have theirs */
820 /* Broad category of texture operation in question */
821 print_texture_op(texture
->op
);
823 /* Specific format in question */
824 print_texture_format(texture
->format
);
826 /* Instruction "modifiers" parallel the ALU instructions. First group
827 * are modifiers that act alone */
829 if (!texture
->filter
)
841 /* Second set are modifiers which take an extra argument each */
843 if (texture
->has_offset
)
851 print_texture_reg(texture
->out_full
, texture
->out_reg_select
, texture
->out_upper
);
852 print_mask(texture
->mask
);
855 printf("texture%d, ", texture
->texture_handle
);
857 printf("sampler%d", texture
->sampler_handle
);
858 print_swizzle(texture
->swizzle
);
861 print_texture_reg(/*texture->in_reg_full*/true, texture
->in_reg_select
, texture
->in_reg_upper
);
862 printf(".%c%c, ", "xyzw"[texture
->in_reg_swizzle_left
],
863 "xyzw"[texture
->in_reg_swizzle_right
]);
865 /* TODO: can offsets be full words? */
866 if (texture
->has_offset
) {
867 print_texture_reg(false, texture
->offset_reg_select
, texture
->offset_reg_upper
);
872 printf("%f, ", texture
->bias
/ 256.0f
);
876 /* While not zero in general, for these simple instructions the
877 * following unknowns are zero, so we don't include them */
879 if (texture
->unknown1
||
887 printf("// unknown1 = 0x%x\n", texture
->unknown1
);
888 printf("// unknown2 = 0x%x\n", texture
->unknown2
);
889 printf("// unknown3 = 0x%x\n", texture
->unknown3
);
890 printf("// unknown4 = 0x%x\n", texture
->unknown4
);
891 printf("// unknownA = 0x%x\n", texture
->unknownA
);
892 printf("// unknownB = 0x%x\n", texture
->unknownB
);
893 printf("// unknown8 = 0x%x\n", texture
->unknown8
);
894 printf("// unknown9 = 0x%x\n", texture
->unknown9
);
897 /* Similarly, if no offset is applied, these are zero. If an offset
898 * -is- applied, or gradients are used, etc, these are nonzero but
899 * largely unknown still. */
901 if (texture
->offset_unknown1
||
902 texture
->offset_reg_select
||
903 texture
->offset_reg_upper
||
904 texture
->offset_unknown4
||
905 texture
->offset_unknown5
||
906 texture
->offset_unknown6
||
907 texture
->offset_unknown7
||
908 texture
->offset_unknown8
||
909 texture
->offset_unknown9
) {
910 printf("// offset_unknown1 = 0x%x\n", texture
->offset_unknown1
);
911 printf("// offset_reg_select = 0x%x\n", texture
->offset_reg_select
);
912 printf("// offset_reg_upper = 0x%x\n", texture
->offset_reg_upper
);
913 printf("// offset_unknown4 = 0x%x\n", texture
->offset_unknown4
);
914 printf("// offset_unknown5 = 0x%x\n", texture
->offset_unknown5
);
915 printf("// offset_unknown6 = 0x%x\n", texture
->offset_unknown6
);
916 printf("// offset_unknown7 = 0x%x\n", texture
->offset_unknown7
);
917 printf("// offset_unknown8 = 0x%x\n", texture
->offset_unknown8
);
918 printf("// offset_unknown9 = 0x%x\n", texture
->offset_unknown9
);
922 if (texture
->unknown7
!= 0x1)
923 printf("// (!) unknown7 = %d\n", texture
->unknown7
);
927 disassemble_midgard(uint8_t *code
, size_t size
)
929 uint32_t *words
= (uint32_t *) code
;
930 unsigned num_words
= size
/ 4;
933 bool prefetch_flag
= false;
937 while (i
< num_words
) {
938 unsigned num_quad_words
= midgard_word_size
[words
[i
] & 0xF];
940 switch (midgard_word_types
[words
[i
] & 0xF]) {
941 case midgard_word_type_texture
:
942 print_texture_word(&words
[i
], tabs
);
945 case midgard_word_type_load_store
:
946 print_load_store_word(&words
[i
], tabs
);
949 case midgard_word_type_alu
:
950 print_alu_word(&words
[i
], num_quad_words
, tabs
);
955 /* Reset word static analysis state */
956 is_embedded_constant_half
= false;
957 is_embedded_constant_int
= false;
962 printf("Unknown word type %u:\n", words
[i
] & 0xF);
964 print_quad_word(&words
[i
], tabs
);
971 unsigned next
= (words
[i
] & 0xF0) >> 4;
973 i
+= 4 * num_quad_words
;
975 /* Break based on instruction prefetch flag */
977 if (i
< num_words
&& next
== 1) {
978 prefetch_flag
= true;
980 if (midgard_word_types
[words
[i
] & 0xF] != midgard_word_type_alu
)