Module: Mesa Branch: main Commit: fa735aacbf3a238d359e9bb640b0a50db82987ec URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=fa735aacbf3a238d359e9bb640b0a50db82987ec
Author: Mark Collins <[email protected]> Date: Fri Dec 1 12:02:36 2023 +0000 freedreno/rddecompiler: Decode ELSE branches using NOPs In newer traces, in any cases where instructions need to be executed for both cases of a predicate, such as for GMEM/sysmem. The proprietary driver emits the TRUE and FALSE body one after another with a NOP at the end of the TRUE condition body so the CP skips over the FALSE body. Currently, the NOP skips over all instructions in the ELSE body which results in them not being decoded whatsoever. This commit checks if we encounter any NOPs while in a conditional block and appropriately parses out them out into their own ELSE scope when we do. Signed-off-by: Mark Collins <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26465> --- src/freedreno/decode/rddecompiler.c | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/freedreno/decode/rddecompiler.c b/src/freedreno/decode/rddecompiler.c index 9f5cb135856..03fecdf3eeb 100644 --- a/src/freedreno/decode/rddecompiler.c +++ b/src/freedreno/decode/rddecompiler.c @@ -369,7 +369,7 @@ decompile_domain(uint32_t pkt, uint32_t *dwords, uint32_t sizedwords, } static void -decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) +decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level, uint32_t *cond_count) { int dwords_left = sizedwords; uint32_t count = 0; /* dword count including packet header */ @@ -396,7 +396,7 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) printlvl(level + 1, "begin_ib();\n"); uint32_t *ptr = hostptr(ibaddr); - decompile_commands(ptr, ibsize, level + 1); + decompile_commands(ptr, ibsize, level + 1, NULL); printlvl(level + 1, "end_ib();\n"); printlvl(level, "}\n"); @@ -412,7 +412,7 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) printlvl(level + 1, "begin_draw_state();\n"); uint32_t *ptr = hostptr(ibaddr); - decompile_commands(ptr, state_count, level + 1); + decompile_commands(ptr, state_count, level + 1, NULL); printlvl(level + 1, "end_draw_state(%u);\n", unchanged); printlvl(level, "}\n"); @@ -466,11 +466,41 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) printlvl(level, "{\n"); printlvl(level + 1, "/* BEGIN COND (%d DWORDS) */\n", cond_count); - decompile_commands(dwords + count, cond_count, level + 1); + decompile_commands(dwords + count, cond_count, level + 1, &cond_count); count += cond_count; printlvl(level + 1, "/* END COND */\n"); printlvl(level, "}\n"); + } else if (val == CP_NOP) { + /* Prop will often use NOP past the end of cond execs + * which basically create an else path for the cond exec + */ + const char *packet_name = pktname(val); + const char *dom_name = packet_name; + + if (count > dwords_left) { + int else_cond_count = count - dwords_left; + + assert(cond_count); + *cond_count += else_cond_count; + + printlvl(level, "pkt7(cs, %s, %u);\n", packet_name, count - 1); + for (int i = 1; i < dwords_left; i++) { + printlvl(level, "pkt(cs, 0x%x);\n", dwords[i]); + } + + printlvl(level, "/* TO ELSE COND */\n"); + printlvl(level - 1, "}\n"); + + printlvl(level - 1, "{\n"); + printlvl(level, "/* ELSE COND (%d DWORDS) */\n", else_cond_count); + decompile_commands(dwords + dwords_left, else_cond_count, level, NULL); + + return; + } else { + decompile_domain(val, dwords + 1, count - 1, dom_name, packet_name, + level); + } } else { const char *packet_name = pktname(val); const char *dom_name = packet_name; @@ -596,7 +626,7 @@ handle_file(const char *filename, uint32_t submit_to_decompile) parse_addr(ps.buf, ps.sz, &sizedwords, &gpuaddr); if (submit == submit_to_decompile) { - decompile_commands(hostptr(gpuaddr), sizedwords, 0); + decompile_commands(hostptr(gpuaddr), sizedwords, 0, NULL); } submit++;
