Mesa (main): freedreno/afuc: Use emulator to extract jmptbl
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jun 1 00:30:14 UTC 2021
Module: Mesa
Branch: main
Commit: ff5e17f1f85c93aa0c0c1004938a21145b0f8b5d
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=ff5e17f1f85c93aa0c0c1004938a21145b0f8b5d
Author: Rob Clark <robdclark at chromium.org>
Date: Mon May 24 11:00:28 2021 -0700
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 at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10944>
---
src/freedreno/.gitlab-ci/reference/afuc_test.asm | 128 +++++++++++++++++++++++
src/freedreno/afuc/disasm.c | 103 +++++++++++++++---
2 files changed, 215 insertions(+), 16 deletions(-)
diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.asm b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
index c68460477bb..920aa4d49d3 100644
--- a/src/freedreno/.gitlab-ci/reference/afuc_test.asm
+++ b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
@@ -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
diff --git a/src/freedreno/afuc/disasm.c b/src/freedreno/afuc/disasm.c
index 8de7991ebbd..d7b322a1022 100644
--- a/src/freedreno/afuc/disasm.c
+++ b/src/freedreno/afuc/disasm.c
@@ -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;
}
More information about the mesa-commit
mailing list