diff --git a/src/freedreno/.gitlab-ci/reference/afuc_test.asm b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
index 7316504a51d..aa0f370cd66 100644
--- a/src/freedreno/.gitlab-ci/reference/afuc_test.asm
+++ b/src/freedreno/.gitlab-ci/reference/afuc_test.asm
@@ -19,10 +19,10 @@ CP_ME_INIT:
mov $01, $data
CP_MEM_WRITE:
- mov $addr, 0x00a0 << 24
+ mov $addr, 0x00a0 << 24 ; |NRT_ADDR
mov $02, 0x0004
(xmov1)add $data, $02, $data
- mov $addr, 0xa204 << 16
+ mov $addr, 0xa204 << 16 ; |NRT_DATA
(rep)(xmov3)mov $data, $data
waitin
mov $01, $data
diff --git a/src/freedreno/afuc/disasm.c b/src/freedreno/afuc/disasm.c
index 6dfccb2eae9..145fdbda9a7 100644
--- a/src/freedreno/afuc/disasm.c
+++ b/src/freedreno/afuc/disasm.c
@@ -269,6 +269,18 @@ print_control_reg(uint32_t id)
}
}
+static void
+print_pipe_reg(uint32_t id)
+{
+ char *name = afuc_pipe_reg_name(id);
+ if (name) {
+ printf("|%s", name);
+ free(name);
+ } else {
+ printf("0x%03x", id);
+ }
+}
+
static void
disasm_instr(uint32_t *instrs, unsigned pc)
{
@@ -385,6 +397,16 @@ disasm_instr(uint32_t *instrs, unsigned pc)
if (instr->movi.shift)
printf(" << %u", instr->movi.shift);
+ if ((instr->movi.dst == REG_ADDR) && (instr->movi.shift >= 16)) {
+ uint32_t val = instr->movi.uimm << instr->movi.shift;
+ val &= ~0x40000; /* b18 seems to be a flag */
+
+ if ((val & 0x00ffffff) == 0) {
+ printf("\t; ");
+ print_pipe_reg(val >> 24);
+ break;
+ }
+ }
/* using mov w/ << 16 is popular way to construct a pkt7
* header to send (for ex, from PFP to ME), so check that
* case first
diff --git a/src/freedreno/afuc/util.c b/src/freedreno/afuc/util.c
index b48cc7a3087..c0be0926816 100644
--- a/src/freedreno/afuc/util.c
+++ b/src/freedreno/afuc/util.c
@@ -34,6 +34,7 @@
static struct rnndeccontext *ctx;
static struct rnndb *db;
static struct rnndomain *control_regs;
+static struct rnndomain *pipe_regs;
struct rnndomain *dom[2];
static struct rnnenum *pm4_packets;
@@ -47,22 +48,41 @@ find_reg(struct rnndomain *dom, const char *name)
return -1;
}
+static unsigned
+reg(struct rnndomain *dom, const char *type, const char *name)
+{
+ int val = find_reg(dom, name);
+ if (val < 0) {
+ char *endptr = NULL;
+ val = strtol(name, &endptr, 0);
+ if (endptr && *endptr) {
+ printf("invalid %s reg: %s\n", type, name);
+ exit(2);
+ }
+ }
+ return (unsigned)val;
+}
+
+static char *
+reg_name(struct rnndomain *dom, unsigned id)
+{
+ if (rnndec_checkaddr(ctx, dom, id, 0)) {
+ struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, dom, id, 0);
+ char *name = info->name;
+ free(info);
+ return name;
+ } else {
+ return NULL;
+ }
+}
+
/**
* Map control reg name to offset.
*/
unsigned
afuc_control_reg(const char *name)
{
- int val = find_reg(control_regs, name);
- if (val < 0) {
- char *endptr = NULL;
- val = strtol(name, &endptr, 0);
- if (endptr) {
- printf("invalid control reg: %s\n", name);
- exit(2);
- }
- }
- return (unsigned)val;
+ return reg(control_regs, "control", name);
}
/**
@@ -71,14 +91,25 @@ afuc_control_reg(const char *name)
char *
afuc_control_reg_name(unsigned id)
{
- if (rnndec_checkaddr(ctx, control_regs, id, 0)) {
- struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, control_regs, id, 0);
- char *name = info->name;
- free(info);
- return name;
- } else {
- return NULL;
- }
+ return reg_name(control_regs, id);
+}
+
+/**
+ * Map pipe reg name to offset.
+ */
+unsigned
+afuc_pipe_reg(const char *name)
+{
+ return reg(pipe_regs, "pipe", name);
+}
+
+/**
+ * Map offset to pipe reg name (or NULL), caller frees
+ */
+char *
+afuc_pipe_reg_name(unsigned id)
+{
+ return reg_name(pipe_regs, id);
}
/**
@@ -93,7 +124,7 @@ afuc_gpu_reg(const char *name)
if (val < 0) {
char *endptr = NULL;
val = strtol(name, &endptr, 0);
- if (endptr) {
+ if (endptr && *endptr) {
printf("invalid control reg: %s\n", name);
exit(2);
}
@@ -172,15 +203,18 @@ afuc_printc(enum afuc_color c, const char *fmt, ...)
int afuc_util_init(int gpuver, bool colors)
{
char *name, *control_reg_name;
+ char *pipe_reg_name = NULL;
switch (gpuver) {
case 6:
name = "A6XX";
control_reg_name = "A6XX_CONTROL_REG";
+ pipe_reg_name = "A6XX_PIPE_REG";
break;
case 5:
name = "A5XX";
control_reg_name = "A5XX_CONTROL_REG";
+ pipe_reg_name = "A5XX_PIPE_REG";
break;
default:
fprintf(stderr, "unknown GPU version!\n");
@@ -200,6 +234,7 @@ int afuc_util_init(int gpuver, bool colors)
dom[0] = rnn_finddomain(db, name);
dom[1] = rnn_finddomain(db, "AXXX");
control_regs = rnn_finddomain(db, control_reg_name);
+ pipe_regs = rnn_finddomain(db, pipe_reg_name);
rnndec_varadd(ctx, "chip", name);
diff --git a/src/freedreno/afuc/util.h b/src/freedreno/afuc/util.h
index 436bf63f435..4b70d221ae4 100644
--- a/src/freedreno/afuc/util.h
+++ b/src/freedreno/afuc/util.h
@@ -33,6 +33,9 @@
unsigned afuc_control_reg(const char *name);
char * afuc_control_reg_name(unsigned id);
+unsigned afuc_pipe_reg(const char *name);
+char * afuc_pipe_reg_name(unsigned id);
+
unsigned afuc_gpu_reg(const char *name);
char * afuc_gpu_reg_name(unsigned id);
diff --git a/src/freedreno/registers/adreno/adreno_pipe_regs.xml b/src/freedreno/registers/adreno/adreno_pipe_regs.xml
index d5292694cda..70ce19d7cd1 100644
--- a/src/freedreno/registers/adreno/adreno_pipe_regs.xml
+++ b/src/freedreno/registers/adreno/adreno_pipe_regs.xml
@@ -32,6 +32,9 @@ CP_WAIT_MEM_WRITES:
Special type to mark registers with no payload.
+
+
+