freedreno/afuc: Use emulator to extract jmptbl

This runs through the SQE bootstrap code to extract the packet-table,
rather than relying on heuristics.  As a bonus, it can detect the start
of the LPAC fw in a660+ fw so that we can properly decode the LPAC fw
and packet-table.

Note that this decodes the jmptable as normal instructions, which is a
change in behavior from the previous heuristic based jmptbl extraction.
Not sure if that is a good or bad thing.

For a5xx, for now the legacy heuristic based jmptable decoding is
preserved, at least until enough control regs are figured out.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10944>
This commit is contained in:
Rob Clark
2021-05-24 11:00:28 -07:00
committed by Marge Bot
parent 2beb5b015a
commit ff5e17f1f8
2 changed files with 215 additions and 16 deletions
@@ -260,3 +260,131 @@ UNKN126:
UNKN127:
waitin
mov $01, $data
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[0000006b] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[0000003f] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000025] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000022] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[0000002c] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000030] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000062] ; nop
[00000076] ; nop
[00000055] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
[00000076] ; nop
+87 -16
View File
@@ -758,7 +758,81 @@ setup_labels(uint32_t *instrs, uint32_t sizedwords)
}
static void
disasm(uint32_t *buf, int sizedwords)
disasm(struct emu *emu)
{
uint32_t sizedwords = emu->sizedwords;
uint32_t lpac_offset = 0;
EMU_GPU_REG(CP_SQE_INSTR_BASE);
EMU_GPU_REG(CP_LPAC_SQE_INSTR_BASE);
emu_init(emu);
#ifdef BOOTSTRAP_DEBUG
while (true) {
disasm_instr(emu->instrs, emu->gpr_regs.pc);
emu_step(emu);
}
#endif
emu_run_bootstrap(emu);
/* Figure out if we have LPAC SQE appended: */
if (emu_get_reg64(emu, &CP_LPAC_SQE_INSTR_BASE)) {
lpac_offset = emu_get_reg64(emu, &CP_LPAC_SQE_INSTR_BASE) -
emu_get_reg64(emu, &CP_SQE_INSTR_BASE);
lpac_offset /= 4;
sizedwords = lpac_offset;
}
setup_packet_table(emu->jmptbl, ARRAY_SIZE(emu->jmptbl));
setup_labels(emu->instrs, emu->sizedwords);
/* TODO add option to emulate LPAC SQE instead: */
if (emulator) {
/* Start from clean slate: */
emu_fini(emu);
emu_init(emu);
while (true) {
disasm_instr(emu->instrs, emu->gpr_regs.pc);
emu_step(emu);
}
}
/* print instructions: */
for (int i = 0; i < sizedwords; i++) {
disasm_instr(emu->instrs, i);
}
if (!lpac_offset)
return;
printf(";\n");
printf("; LPAC microcode:\n");
printf(";\n");
emu_fini(emu);
emu->lpac = true;
emu->instrs += lpac_offset;
emu->sizedwords -= lpac_offset;
emu_init(emu);
emu_run_bootstrap(emu);
setup_packet_table(emu->jmptbl, ARRAY_SIZE(emu->jmptbl));
setup_labels(emu->instrs, emu->sizedwords);
/* print instructions: */
for (int i = 0; i < emu->sizedwords; i++) {
disasm_instr(emu->instrs, i);
}
}
static void
disasm_legacy(uint32_t *buf, int sizedwords)
{
uint32_t *instrs = buf;
const int jmptbl_start = instrs[1] & 0xffff;
@@ -773,20 +847,6 @@ disasm(uint32_t *buf, int sizedwords)
*/
setup_labels(instrs, jmptbl_start);
if (emulator) {
struct emu state = {
.instrs = instrs,
.sizedwords = sizedwords,
};
emu_init(&state);
while (true) {
disasm_instr(instrs, state.gpr_regs.pc);
emu_step(&state);
}
}
/* print instructions: */
for (i = 0; i < jmptbl_start; i++) {
disasm_instr(instrs, i);
@@ -898,7 +958,18 @@ main(int argc, char **argv)
printf("; Disassembling microcode: %s\n", file);
printf("; Version: %08x\n\n", buf[1]);
disasm(&buf[1], sz / 4 - 1);
if (gpuver < 6) {
disasm_legacy(&buf[1], sz / 4 - 1);
} else {
struct emu emu = {
.instrs = &buf[1],
.sizedwords = sz / 4 - 1,
.gpu_id = gpu_id,
};
disasm(&emu);
}
return 0;
}