summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2021-04-16 11:25:06 -0700
committerMarge Bot <eric+marge@anholt.net>2021-04-17 15:38:56 +0000
commit45856c5fbc68c942f3377e6784f15eec362979a4 (patch)
treeb920a59d9e8251e7d33a5e2d06466c1ea8312c15
parent3894bc966424cad8dd393287137e5df028776414 (diff)
freedreno/decode: Re-indent
clang-format -fallback-style=none --style=file -i src/freedreno/decode/*.[ch] Signed-off-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10293>
-rw-r--r--src/freedreno/.clang-format1
-rw-r--r--src/freedreno/decode/buffers.c185
-rw-r--r--src/freedreno/decode/buffers.h6
-rw-r--r--src/freedreno/decode/cffdec.c4130
-rw-r--r--src/freedreno/decode/cffdec.h140
-rw-r--r--src/freedreno/decode/cffdump.c639
-rw-r--r--src/freedreno/decode/crashdec.c1671
-rw-r--r--src/freedreno/decode/io.c199
-rw-r--r--src/freedreno/decode/io.h7
-rw-r--r--src/freedreno/decode/pager.c91
-rw-r--r--src/freedreno/decode/pgmdump.c1864
-rw-r--r--src/freedreno/decode/pgmdump2.c895
-rw-r--r--src/freedreno/decode/redump.h73
-rw-r--r--src/freedreno/decode/rnnutil.c263
-rw-r--r--src/freedreno/decode/rnnutil.h18
-rw-r--r--src/freedreno/decode/script.c974
-rw-r--r--src/freedreno/decode/script.h5
-rw-r--r--src/freedreno/decode/util.h250
18 files changed, 5793 insertions, 5618 deletions
diff --git a/src/freedreno/.clang-format b/src/freedreno/.clang-format
index 876aa38fe7a..fda18d13725 100644
--- a/src/freedreno/.clang-format
+++ b/src/freedreno/.clang-format
@@ -90,6 +90,7 @@ ForEachMacros:
- foreach_batch
- hash_table_foreach
- set_foreach
+ - foreach_line_in_section
IncludeBlocks: Preserve
IncludeCategories:
diff --git a/src/freedreno/decode/buffers.c b/src/freedreno/decode/buffers.c
index a052778a45b..6a73ef276d9 100644
--- a/src/freedreno/decode/buffers.c
+++ b/src/freedreno/decode/buffers.c
@@ -29,143 +29,148 @@
#include <assert.h>
#include <stdlib.h>
-#include "buffers.h"
#include "util/rb_tree.h"
+#include "buffers.h"
struct buffer {
- struct rb_node node;
- void *hostptr;
- unsigned int len;
- uint64_t gpuaddr;
-
- /* for 'once' mode, for buffers containing cmdstream keep track per offset
- * into buffer of which modes it has already been dumped;
- */
- struct {
- unsigned offset;
- unsigned dumped_mask;
- } offsets[64];
- unsigned noffsets;
+ struct rb_node node;
+ void *hostptr;
+ unsigned int len;
+ uint64_t gpuaddr;
+
+ /* for 'once' mode, for buffers containing cmdstream keep track per offset
+ * into buffer of which modes it has already been dumped;
+ */
+ struct {
+ unsigned offset;
+ unsigned dumped_mask;
+ } offsets[64];
+ unsigned noffsets;
};
static struct rb_tree buffers;
-static int buffer_insert_cmp(const struct rb_node *n1, const struct rb_node *n2)
+static int
+buffer_insert_cmp(const struct rb_node *n1, const struct rb_node *n2)
{
- const struct buffer *buf1 = (const struct buffer *) n1;
- const struct buffer *buf2 = (const struct buffer *) n2;
- return buf1->gpuaddr - buf2->gpuaddr;
+ const struct buffer *buf1 = (const struct buffer *)n1;
+ const struct buffer *buf2 = (const struct buffer *)n2;
+ return buf1->gpuaddr - buf2->gpuaddr;
}
-static int buffer_search_cmp(const struct rb_node *node, const void *addrptr)
+static int
+buffer_search_cmp(const struct rb_node *node, const void *addrptr)
{
- const struct buffer *buf = (const struct buffer *) node;
- uint64_t gpuaddr = *(uint64_t *)addrptr;
- if (buf->gpuaddr + buf->len <= gpuaddr)
- return -1;
- else if (buf->gpuaddr > gpuaddr)
- return 1;
- return 0;
+ const struct buffer *buf = (const struct buffer *)node;
+ uint64_t gpuaddr = *(uint64_t *)addrptr;
+ if (buf->gpuaddr + buf->len <= gpuaddr)
+ return -1;
+ else if (buf->gpuaddr > gpuaddr)
+ return 1;
+ return 0;
}
-static struct buffer *get_buffer(uint64_t gpuaddr)
+static struct buffer *
+get_buffer(uint64_t gpuaddr)
{
- if (gpuaddr == 0)
- return NULL;
- return (struct buffer *) rb_tree_search(&buffers, &gpuaddr, buffer_search_cmp);
+ if (gpuaddr == 0)
+ return NULL;
+ return (struct buffer *)rb_tree_search(&buffers, &gpuaddr,
+ buffer_search_cmp);
}
static int
buffer_contains_hostptr(struct buffer *buf, void *hostptr)
{
- return (buf->hostptr <= hostptr) && (hostptr < (buf->hostptr + buf->len));
+ return (buf->hostptr <= hostptr) && (hostptr < (buf->hostptr + buf->len));
}
-
uint64_t
gpuaddr(void *hostptr)
{
- rb_tree_foreach(struct buffer, buf, &buffers, node) {
- if (buffer_contains_hostptr(buf, hostptr))
- return buf->gpuaddr + (hostptr - buf->hostptr);
- }
- return 0;
+ rb_tree_foreach(struct buffer, buf, &buffers, node)
+ {
+ if (buffer_contains_hostptr(buf, hostptr))
+ return buf->gpuaddr + (hostptr - buf->hostptr);
+ }
+ return 0;
}
uint64_t
gpubaseaddr(uint64_t gpuaddr)
{
- struct buffer *buf = get_buffer(gpuaddr);
- if (buf)
- return buf->gpuaddr;
- else
- return 0;
+ struct buffer *buf = get_buffer(gpuaddr);
+ if (buf)
+ return buf->gpuaddr;
+ else
+ return 0;
}
void *
hostptr(uint64_t gpuaddr)
{
- struct buffer *buf = get_buffer(gpuaddr);
- if (buf)
- return buf->hostptr + (gpuaddr - buf->gpuaddr);
- else
- return 0;
+ struct buffer *buf = get_buffer(gpuaddr);
+ if (buf)
+ return buf->hostptr + (gpuaddr - buf->gpuaddr);
+ else
+ return 0;
}
unsigned
hostlen(uint64_t gpuaddr)
{
- struct buffer *buf = get_buffer(gpuaddr);
- if (buf)
- return buf->len + buf->gpuaddr - gpuaddr;
- else
- return 0;
+ struct buffer *buf = get_buffer(gpuaddr);
+ if (buf)
+ return buf->len + buf->gpuaddr - gpuaddr;
+ else
+ return 0;
}
bool
has_dumped(uint64_t gpuaddr, unsigned enable_mask)
{
- if (!gpuaddr)
- return false;
+ if (!gpuaddr)
+ return false;
- struct buffer *b = get_buffer(gpuaddr);
- if (!b)
- return false;
+ struct buffer *b = get_buffer(gpuaddr);
+ if (!b)
+ return false;
- assert(gpuaddr >= b->gpuaddr);
- unsigned offset = gpuaddr - b->gpuaddr;
+ assert(gpuaddr >= b->gpuaddr);
+ unsigned offset = gpuaddr - b->gpuaddr;
- unsigned n = 0;
- while (n < b->noffsets) {
- if (offset == b->offsets[n].offset)
- break;
- n++;
- }
+ unsigned n = 0;
+ while (n < b->noffsets) {
+ if (offset == b->offsets[n].offset)
+ break;
+ n++;
+ }
- /* if needed, allocate a new offset entry: */
- if (n == b->noffsets) {
- b->noffsets++;
- assert(b->noffsets < ARRAY_SIZE(b->offsets));
- b->offsets[n].dumped_mask = 0;
- b->offsets[n].offset = offset;
- }
+ /* if needed, allocate a new offset entry: */
+ if (n == b->noffsets) {
+ b->noffsets++;
+ assert(b->noffsets < ARRAY_SIZE(b->offsets));
+ b->offsets[n].dumped_mask = 0;
+ b->offsets[n].offset = offset;
+ }
- if ((b->offsets[n].dumped_mask & enable_mask) == enable_mask)
- return true;
+ if ((b->offsets[n].dumped_mask & enable_mask) == enable_mask)
+ return true;
- b->offsets[n].dumped_mask |= enable_mask;
+ b->offsets[n].dumped_mask |= enable_mask;
- return false;
+ return false;
}
void
reset_buffers(void)
{
- rb_tree_foreach_safe(struct buffer, buf, &buffers, node) {
- rb_tree_remove(&buffers, &buf->node);
- free(buf->hostptr);
- free(buf);
- }
+ rb_tree_foreach_safe(struct buffer, buf, &buffers, node)
+ {
+ rb_tree_remove(&buffers, &buf->node);
+ free(buf->hostptr);
+ free(buf);
+ }
}
/**
@@ -175,16 +180,16 @@ reset_buffers(void)
void
add_buffer(uint64_t gpuaddr, unsigned int len, void *hostptr)
{
- struct buffer *buf = get_buffer(gpuaddr);
+ struct buffer *buf = get_buffer(gpuaddr);
- if (!buf) {
- buf = calloc(sizeof(struct buffer), 1);
- buf->gpuaddr = gpuaddr;
- rb_tree_insert(&buffers, &buf->node, buffer_insert_cmp);
- }
+ if (!buf) {
+ buf = calloc(sizeof(struct buffer), 1);
+ buf->gpuaddr = gpuaddr;
+ rb_tree_insert(&buffers, &buf->node, buffer_insert_cmp);
+ }
- assert(buf->gpuaddr == gpuaddr);
+ assert(buf->gpuaddr == gpuaddr);
- buf->hostptr = hostptr;
- buf->len = len;
+ buf->hostptr = hostptr;
+ buf->len = len;
}
diff --git a/src/freedreno/decode/buffers.h b/src/freedreno/decode/buffers.h
index f63f3f3ad7d..565b6814b87 100644
--- a/src/freedreno/decode/buffers.h
+++ b/src/freedreno/decode/buffers.h
@@ -24,12 +24,12 @@
#ifndef __BUFFERS_H__
#define __BUFFERS_H__
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
uint64_t gpuaddr(void *hostptr);
uint64_t gpubaseaddr(uint64_t gpuaddr);
-void * hostptr(uint64_t gpuaddr);
+void *hostptr(uint64_t gpuaddr);
unsigned hostlen(uint64_t gpuaddr);
bool has_dumped(uint64_t gpuaddr, unsigned enable_mask);
@@ -37,7 +37,7 @@ void reset_buffers(void);
void add_buffer(uint64_t gpuaddr, unsigned int len, void *hostptr);
#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#endif /* __BUFFERS_H__ */
diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c
index b09ca846156..8cae4a09c23 100644
--- a/src/freedreno/decode/cffdec.c
+++ b/src/freedreno/decode/cffdec.c
@@ -24,28 +24,27 @@
#include <assert.h>
#include <ctype.h>
#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
-#include <fcntl.h>
-#include <string.h>
-#include <assert.h>
-#include <signal.h>
-#include <errno.h>
-#include "redump.h"
-#include "disasm.h"
-#include "script.h"
-#include "rnnutil.h"
#include "buffers.h"
#include "cffdec.h"
+#include "disasm.h"
+#include "redump.h"
+#include "rnnutil.h"
+#include "script.h"
/* ************************************************************************* */
/* originally based on kernel recovery dump code: */
@@ -57,44 +56,45 @@ static bool summary = false;
static bool in_summary = false;
static int vertices;
-static inline unsigned regcnt(void)
+static inline unsigned
+regcnt(void)
{
- if (options->gpu_id >= 500)
- return 0xffff;
- else
- return 0x7fff;
+ if (options->gpu_id >= 500)
+ return 0xffff;
+ else
+ return 0x7fff;
}
-static int is_64b(void)
+static int
+is_64b(void)
{
- return options->gpu_id >= 500;
+ return options->gpu_id >= 500;
}
-
static int draws[4];
static struct {
- uint64_t base;
- uint32_t size; /* in dwords */
- /* Generally cmdstream consists of multiple IB calls to different
- * buffers, which are themselves often re-used for each tile. The
- * triggered flag serves two purposes to help make it more clear
- * what part of the cmdstream is before vs after the the GPU hang:
- *
- * 1) if in IB2 we are passed the point within the IB2 buffer where
- * the GPU hung, but IB1 is not passed the point within its
- * buffer where the GPU had hung, then we know the GPU hang
- * happens on a future use of that IB2 buffer.
- *
- * 2) if in an IB1 or IB2 buffer that is not the one where the GPU
- * hung, but we've already passed the trigger point at the same
- * IB level, we know that we are passed the point where the GPU
- * had hung.
- *
- * So this is a one way switch, false->true. And a higher #'d
- * IB level isn't considered triggered unless the lower #'d IB
- * level is.
- */
- bool triggered;
+ uint64_t base;
+ uint32_t size; /* in dwords */
+ /* Generally cmdstream consists of multiple IB calls to different
+ * buffers, which are themselves often re-used for each tile. The
+ * triggered flag serves two purposes to help make it more clear
+ * what part of the cmdstream is before vs after the the GPU hang:
+ *
+ * 1) if in IB2 we are passed the point within the IB2 buffer where
+ * the GPU hung, but IB1 is not passed the point within its
+ * buffer where the GPU had hung, then we know the GPU hang
+ * happens on a future use of that IB2 buffer.
+ *
+ * 2) if in an IB1 or IB2 buffer that is not the one where the GPU
+ * hung, but we've already passed the trigger point at the same
+ * IB level, we know that we are passed the point where the GPU
+ * had hung.
+ *
+ * So this is a one way switch, false->true. And a higher #'d
+ * IB level isn't considered triggered unless the lower #'d IB
+ * level is.
+ */
+ bool triggered;
} ibs[4];
static int ib;
@@ -110,161 +110,163 @@ static int *queryvals;
static bool
quiet(int lvl)
{
- if ((options->draw_filter != -1) && (options->draw_filter != current_draw_count))
- return true;
- if ((lvl >= 3) && (summary || options->querystrs || options->script))
- return true;
- if ((lvl >= 2) && (options->querystrs || options->script))
- return true;
- return false;
+ if ((options->draw_filter != -1) &&
+ (options->draw_filter != current_draw_count))
+ return true;
+ if ((lvl >= 3) && (summary || options->querystrs || options->script))
+ return true;
+ if ((lvl >= 2) && (options->querystrs || options->script))
+ return true;
+ return false;
}
void
printl(int lvl, const char *fmt, ...)
{
- va_list args;
- if (quiet(lvl))
- return;
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
+ va_list args;
+ if (quiet(lvl))
+ return;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
}
static const char *levels[] = {
- "\t",
- "\t\t",
- "\t\t\t",
- "\t\t\t\t",
- "\t\t\t\t\t",
- "\t\t\t\t\t\t",
- "\t\t\t\t\t\t\t",
- "\t\t\t\t\t\t\t\t",
- "\t\t\t\t\t\t\t\t\t",
- "x",
- "x",
- "x",
- "x",
- "x",
- "x",
+ "\t",
+ "\t\t",
+ "\t\t\t",
+ "\t\t\t\t",
+ "\t\t\t\t\t",
+ "\t\t\t\t\t\t",
+ "\t\t\t\t\t\t\t",
+ "\t\t\t\t\t\t\t\t",
+ "\t\t\t\t\t\t\t\t\t",
+ "x",
+ "x",
+ "x",
+ "x",
+ "x",
+ "x",
};
enum state_src_t {
- STATE_SRC_DIRECT,
- STATE_SRC_INDIRECT,
- STATE_SRC_BINDLESS,
+ STATE_SRC_DIRECT,
+ STATE_SRC_INDIRECT,
+ STATE_SRC_BINDLESS,
};
/* SDS (CP_SET_DRAW_STATE) helpers: */
static void load_all_groups(int level);
static void disable_all_groups(void);
-static void dump_tex_samp(uint32_t *texsamp, enum state_src_t src, int num_unit, int level);
+static void dump_tex_samp(uint32_t *texsamp, enum state_src_t src, int num_unit,
+ int level);
static void dump_tex_const(uint32_t *texsamp, int num_unit, int level);
static bool
highlight_gpuaddr(uint64_t gpuaddr)
{
- if (!options->color)
- return false;
+ if (!options->color)
+ return false;
- if (!options->ibs[ib].base)
- return false;
+ if (!options->ibs[ib].base)
+ return false;
- if ((ib > 0) && options->ibs[ib-1].base && !ibs[ib-1].triggered)
- return false;
+ if ((ib > 0) && options->ibs[ib - 1].base && !ibs[ib - 1].triggered)
+ return false;
- if (ibs[ib].triggered)
- return true;
+ if (ibs[ib].triggered)
+ return true;
- if (options->ibs[ib].base != ibs[ib].base)
- return false;
+ if (options->ibs[ib].base != ibs[ib].base)
+ return false;
- uint64_t start = ibs[ib].base + 4 * (ibs[ib].size - options->ibs[ib].rem);
- uint64_t end = ibs[ib].base + 4 * ibs[ib].size;
+ uint64_t start = ibs[ib].base + 4 * (ibs[ib].size - options->ibs[ib].rem);
+ uint64_t end = ibs[ib].base + 4 * ibs[ib].size;
- bool triggered = (start <= gpuaddr) && (gpuaddr <= end);
+ bool triggered = (start <= gpuaddr) && (gpuaddr <= end);
- ibs[ib].triggered |= triggered;
+ ibs[ib].triggered |= triggered;
- if (triggered)
- printf("ESTIMATED CRASH LOCATION!\n");
+ if (triggered)
+ printf("ESTIMATED CRASH LOCATION!\n");
- return triggered;
+ return triggered;
}
static void
dump_hex(uint32_t *dwords, uint32_t sizedwords, int level)
{
- int i, j;
- int lastzero = 1;
+ int i, j;
+ int lastzero = 1;
- if (quiet(2))
- return;
+ if (quiet(2))
+ return;
- for (i = 0; i < sizedwords; i += 8) {
- int zero = 1;
+ for (i = 0; i < sizedwords; i += 8) {
+ int zero = 1;
- /* always show first row: */
- if (i == 0)
- zero = 0;
+ /* always show first row: */
+ if (i == 0)
+ zero = 0;
- for (j = 0; (j < 8) && (i+j < sizedwords) && zero; j++)
- if (dwords[i+j])
- zero = 0;
+ for (j = 0; (j < 8) && (i + j < sizedwords) && zero; j++)
+ if (dwords[i + j])
+ zero = 0;
- if (zero && !lastzero)
- printf("*\n");
+ if (zero && !lastzero)
+ printf("*\n");
- lastzero = zero;
+ lastzero = zero;
- if (zero)
- continue;
+ if (zero)
+ continue;
- uint64_t addr = gpuaddr(&dwords[i]);
- bool highlight = highlight_gpuaddr(addr);
+ uint64_t addr = gpuaddr(&dwords[i]);
+ bool highlight = highlight_gpuaddr(addr);
- if (highlight)
- printf("\x1b[0;1;31m");
+ if (highlight)
+ printf("\x1b[0;1;31m");
- if (is_64b()) {
- printf("%016"PRIx64":%s", addr, levels[level]);
- } else {
- printf("%08x:%s", (uint32_t)addr, levels[level]);
- }
+ if (is_64b()) {
+ printf("%016" PRIx64 ":%s", addr, levels[level]);
+ } else {
+ printf("%08x:%s", (uint32_t)addr, levels[level]);
+ }
- if (highlight)
- printf("\x1b[0m");
+ if (highlight)
+ printf("\x1b[0m");
- printf("%04x:", i * 4);
+ printf("%04x:", i * 4);
- for (j = 0; (j < 8) && (i+j < sizedwords); j++) {
- printf(" %08x", dwords[i+j]);
- }
+ for (j = 0; (j < 8) && (i + j < sizedwords); j++) {
+ printf(" %08x", dwords[i + j]);
+ }
- printf("\n");
- }
+ printf("\n");
+ }
}
static void
dump_float(float *dwords, uint32_t sizedwords, int level)
{
- int i;
- for (i = 0; i < sizedwords; i++) {
- if ((i % 8) == 0) {
- if (is_64b()) {
- printf("%016"PRIx64":%s", gpuaddr(dwords), levels[level]);
- } else {
- printf("%08x:%s", (uint32_t)gpuaddr(dwords), levels[level]);
- }
- } else {
- printf(" ");
- }
- printf("%8f", *(dwords++));
- if ((i % 8) == 7)
- printf("\n");
- }
- if (i % 8)
- printf("\n");
+ int i;
+ for (i = 0; i < sizedwords; i++) {
+ if ((i % 8) == 0) {
+ if (is_64b()) {
+ printf("%016" PRIx64 ":%s", gpuaddr(dwords), levels[level]);
+ } else {
+ printf("%08x:%s", (uint32_t)gpuaddr(dwords), levels[level]);
+ }
+ } else {
+ printf(" ");
+ }
+ printf("%8f", *(dwords++));
+ if ((i % 8) == 7)
+ printf("\n");
+ }
+ if (i % 8)
+ printf("\n");
}
/* I believe the surface format is low bits:
@@ -272,201 +274,207 @@ dump_float(float *dwords, uint32_t sizedwords, int level)
comments in sys2gmem_tex_const indicate that address is [31:12], but
looks like at least some of the bits above the format have different meaning..
*/
-static void parse_dword_addr(uint32_t dword, uint32_t *gpuaddr,
- uint32_t *flags, uint32_t mask)
+static void
+parse_dword_addr(uint32_t dword, uint32_t *gpuaddr, uint32_t *flags,
+ uint32_t mask)
{
- assert(!is_64b()); /* this is only used on a2xx */
- *gpuaddr = dword & ~mask;
- *flags = dword & mask;
+ assert(!is_64b()); /* this is only used on a2xx */
+ *gpuaddr = dword & ~mask;
+ *flags = dword & mask;
}
static uint32_t type0_reg_vals[0xffff + 1];
-static uint8_t type0_reg_rewritten[sizeof(type0_reg_vals)/8]; /* written since last draw */
-static uint8_t type0_reg_written[sizeof(type0_reg_vals)/8];
+static uint8_t type0_reg_rewritten[sizeof(type0_reg_vals) /
+ 8]; /* written since last draw */
+static uint8_t type0_reg_written[sizeof(type0_reg_vals) / 8];
static uint32_t lastvals[ARRAY_SIZE(type0_reg_vals)];
-static bool reg_rewritten(uint32_t regbase)
+static bool
+reg_rewritten(uint32_t regbase)
{
- return !!(type0_reg_rewritten[regbase/8] & (1 << (regbase % 8)));
+ return !!(type0_reg_rewritten[regbase / 8] & (1 << (regbase % 8)));
}
-bool reg_written(uint32_t regbase)
+bool
+reg_written(uint32_t regbase)
{
- return !!(type0_reg_written[regbase/8] & (1 << (regbase % 8)));
+ return !!(type0_reg_written[regbase / 8] & (1 << (regbase % 8)));
}
-static void clear_rewritten(void)
+static void
+clear_rewritten(void)
{
- memset(type0_reg_rewritten, 0, sizeof(type0_reg_rewritten));
+ memset(type0_reg_rewritten, 0, sizeof(type0_reg_rewritten));
}
-static void clear_written(void)
+static void
+clear_written(void)
{
- memset(type0_reg_written, 0, sizeof(type0_reg_written));
- clear_rewritten();
+ memset(type0_reg_written, 0, sizeof(type0_reg_written));
+ clear_rewritten();
}
-uint32_t reg_lastval(uint32_t regbase)
+uint32_t
+reg_lastval(uint32_t regbase)
{
- return lastvals[regbase];
+ return lastvals[regbase];
}
static void
clear_lastvals(void)
{
- memset(lastvals, 0, sizeof(lastvals));
+ memset(lastvals, 0, sizeof(lastvals));
}
uint32_t
reg_val(uint32_t regbase)
{
- return type0_reg_vals[regbase];
+ return type0_reg_vals[regbase];
}
void
reg_set(uint32_t regbase, uint32_t val)
{
- assert(regbase < regcnt());
- type0_reg_vals[regbase] = val;
- type0_reg_written[regbase/8] |= (1 << (regbase % 8));
- type0_reg_rewritten[regbase/8] |= (1 << (regbase % 8));
+ assert(regbase < regcnt());
+ type0_reg_vals[regbase] = val;
+ type0_reg_written[regbase / 8] |= (1 << (regbase % 8));
+ type0_reg_rewritten[regbase / 8] |= (1 << (regbase % 8));
}
static void
reg_dump_scratch(const char *name, uint32_t dword, int level)
{
- unsigned r;
+ unsigned r;
- if (quiet(3))
- return;
+ if (quiet(3))
+ return;
- r = regbase("CP_SCRATCH[0].REG");
+ r = regbase("CP_SCRATCH[0].REG");
- // if not, try old a2xx/a3xx version:
- if (!r)
- r = regbase("CP_SCRATCH_REG0");
+ // if not, try old a2xx/a3xx version:
+ if (!r)
+ r = regbase("CP_SCRATCH_REG0");
- if (!r)
- return;
+ if (!r)
+ return;
- printf("%s:%u,%u,%u,%u\n", levels[level],
- reg_val(r + 4), reg_val(r + 5),
- reg_val(r + 6), reg_val(r + 7));
+ printf("%s:%u,%u,%u,%u\n", levels[level], reg_val(r + 4), reg_val(r + 5),
+ reg_val(r + 6), reg_val(r + 7));
}
static void
dump_gpuaddr_size(uint64_t gpuaddr, int level, int sizedwords, int quietlvl)
{
- void *buf;
+ void *buf;
- if (quiet(quietlvl))
- return;
+ if (quiet(quietlvl))
+ return;
- buf = hostptr(gpuaddr);
- if (buf) {
- dump_hex(buf, sizedwords, level+1);
- }
+ buf = hostptr(gpuaddr);
+ if (buf) {
+ dump_hex(buf, sizedwords, level + 1);
+ }
}
static void
dump_gpuaddr(uint64_t gpuaddr, int level)
{
- dump_gpuaddr_size(gpuaddr, level, 64, 3);
+ dump_gpuaddr_size(gpuaddr, level, 64, 3);
}
static void
reg_dump_gpuaddr(const char *name, uint32_t dword, int level)
{
- dump_gpuaddr(dword, level);
+ dump_gpuaddr(dword, level);
}
uint32_t gpuaddr_lo;
static void
reg_gpuaddr_lo(const char *name, uint32_t dword, int level)
{
- gpuaddr_lo = dword;
+ gpuaddr_lo = dword;
}
static void
reg_dump_gpuaddr_hi(const char *name, uint32_t dword, int level)
{
- dump_gpuaddr(gpuaddr_lo | (((uint64_t)dword) << 32), level);
+ dump_gpuaddr(gpuaddr_lo | (((uint64_t)dword) << 32), level);
}
static void
reg_dump_gpuaddr64(const char *name, uint64_t qword, int level)
{
- dump_gpuaddr(qword, level);
+ dump_gpuaddr(qword, level);
}
static void
dump_shader(const char *ext, void *buf, int bufsz)
{
- if (options->dump_shaders) {
- static int n = 0;
- char filename[16];
- int fd;
- sprintf(filename, "%04d.%s", n++, ext);
- fd = open(filename, O_WRONLY| O_TRUNC | O_CREAT, 0644);
- if (fd != -1) {
- write(fd, buf, bufsz);
- close(fd);
- }
- }
+ if (options->dump_shaders) {
+ static int n = 0;
+ char filename[16];
+ int fd;
+ sprintf(filename, "%04d.%s", n++, ext);
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
+ if (fd != -1) {
+ write(fd, buf, bufsz);
+ close(fd);
+ }
+ }
}
static void
disasm_gpuaddr(const char *name, uint64_t gpuaddr, int level)
{
- void *buf;
+ void *buf;
- gpuaddr &= 0xfffffffffffffff0;
+ gpuaddr &= 0xfffffffffffffff0;
- if (quiet(3))
- return;
+ if (quiet(3))
+ return;
- buf = hostptr(gpuaddr);
- if (buf) {
- uint32_t sizedwords = hostlen(gpuaddr) / 4;
- const char *ext;
+ buf = hostptr(gpuaddr);
+ if (buf) {
+ uint32_t sizedwords = hostlen(gpuaddr) / 4;
+ const char *ext;
- dump_hex(buf, min(64, sizedwords), level+1);
- try_disasm_a3xx(buf, sizedwords, level+2, stdout, options->gpu_id);
+ dump_hex(buf, min(64, sizedwords), level + 1);
+ try_disasm_a3xx(buf, sizedwords, level + 2, stdout, options->gpu_id);
- /* this is a bit ugly way, but oh well.. */
- if (strstr(name, "SP_VS_OBJ")) {
- ext = "vo3";
- } else if (strstr(name, "SP_FS_OBJ")) {
- ext = "fo3";
- } else if (strstr(name, "SP_GS_OBJ")) {
- ext = "go3";
- } else if (strstr(name, "SP_CS_OBJ")) {
- ext = "co3";
- } else {
- ext = NULL;
- }
+ /* this is a bit ugly way, but oh well.. */
+ if (strstr(name, "SP_VS_OBJ")) {
+ ext = "vo3";
+ } else if (strstr(name, "SP_FS_OBJ")) {
+ ext = "fo3";
+ } else if (strstr(name, "SP_GS_OBJ")) {
+ ext = "go3";
+ } else if (strstr(name, "SP_CS_OBJ")) {
+ ext = "co3";
+ } else {
+ ext = NULL;
+ }
- if (ext)
- dump_shader(ext, buf, sizedwords * 4);
- }
+ if (ext)
+ dump_shader(ext, buf, sizedwords * 4);
+ }
}
static void
reg_disasm_gpuaddr(const char *name, uint32_t dword, int level)
{
- disasm_gpuaddr(name, dword, level);
+ disasm_gpuaddr(name, dword, level);
}
static void
reg_disasm_gpuaddr_hi(const char *name, uint32_t dword, int level)
{
- disasm_gpuaddr(name, gpuaddr_lo | (((uint64_t)dword) << 32), level);
+ disasm_gpuaddr(name, gpuaddr_lo | (((uint64_t)dword) << 32), level);
}
static void
reg_disasm_gpuaddr64(const char *name, uint64_t qword, int level)
{
- disasm_gpuaddr(name, qword, level);
+ disasm_gpuaddr(name, qword, level);
}
/* Find the value of the TEX_COUNT register that corresponds to the named
@@ -479,225 +487,225 @@ reg_disasm_gpuaddr64(const char *name, uint64_t qword, int level)
static int
get_tex_count(const char *name)
{
- char count_reg[strlen(name) + 5];
- char *p;
+ char count_reg[strlen(name) + 5];
+ char *p;
- p = strstr(name, "CONST");
- if (!p)
- p = strstr(name, "SAMP");
- if (!p)
- return 0;
+ p = strstr(name, "CONST");
+ if (!p)
+ p = strstr(name, "SAMP");
+ if (!p)
+ return 0;
- int n = p - name;
- strncpy(count_reg, name, n);
- strcpy(count_reg + n, "COUNT");
+ int n = p - name;
+ strncpy(count_reg, name, n);
+ strcpy(count_reg + n, "COUNT");
- return reg_val(regbase(count_reg));
+ return reg_val(regbase(count_reg));
}
static void
reg_dump_tex_samp_hi(const char *name, uint32_t dword, int level)
{
- if (!in_summary)
- return;
+ if (!in_summary)
+ return;
- int num_unit = get_tex_count(name);
- uint64_t gpuaddr = gpuaddr_lo | (((uint64_t)dword) << 32);
- void *buf = hostptr(gpuaddr);
+ int num_unit = get_tex_count(name);
+ uint64_t gpuaddr = gpuaddr_lo | (((uint64_t)dword) << 32);
+ void *buf = hostptr(gpuaddr);
- if (!buf)
- return;
+ if (!buf)
+ return;
- dump_tex_samp(buf, STATE_SRC_DIRECT, num_unit, level+1);
+ dump_tex_samp(buf, STATE_SRC_DIRECT, num_unit, level + 1);
}
static void
reg_dump_tex_const_hi(const char *name, uint32_t dword, int level)
{
- if (!in_summary)
- return;
+ if (!in_summary)
+ return;
- int num_unit = get_tex_count(name);
- uint64_t gpuaddr = gpuaddr_lo | (((uint64_t)dword) << 32);
- void *buf = hostptr(gpuaddr);
+ int num_unit = get_tex_count(name);
+ uint64_t gpuaddr = gpuaddr_lo | (((uint64_t)dword) << 32);
+ void *buf = hostptr(gpuaddr);
- if (!buf)
- return;
+ if (!buf)
+ return;
- dump_tex_const(buf, num_unit, level+1);
+ dump_tex_const(buf, num_unit, level + 1);
}
/*
* Registers with special handling (rnndec_decode() handles rest):
*/
-#define REG(x, fxn) { #x, fxn }
-#define REG64(x, fxn) { #x, .fxn64 = fxn, .is_reg64 = true }
+#define REG(x, fxn) { #x, fxn }
+#define REG64(x, fxn) { #x, .fxn64 = fxn, .is_reg64 = true }
static struct {
- const char *regname;
- void (*fxn)(const char *name, uint32_t dword, int level);
- void (*fxn64)(const char *name, uint64_t qword, int level);
- uint32_t regbase;
- bool is_reg64;
+ const char *regname;
+ void (*fxn)(const char *name, uint32_t dword, int level);
+ void (*fxn64)(const char *name, uint64_t qword, int level);
+ uint32_t regbase;
+ bool is_reg64;
} reg_a2xx[] = {
- REG(CP_SCRATCH_REG0, reg_dump_scratch),
- REG(CP_SCRATCH_REG1, reg_dump_scratch),
- REG(CP_SCRATCH_REG2, reg_dump_scratch),
- REG(CP_SCRATCH_REG3, reg_dump_scratch),
- REG(CP_SCRATCH_REG4, reg_dump_scratch),
- REG(CP_SCRATCH_REG5, reg_dump_scratch),
- REG(CP_SCRATCH_REG6, reg_dump_scratch),
- REG(CP_SCRATCH_REG7, reg_dump_scratch),
- {NULL},
+ REG(CP_SCRATCH_REG0, reg_dump_scratch),
+ REG(CP_SCRATCH_REG1, reg_dump_scratch),
+ REG(CP_SCRATCH_REG2, reg_dump_scratch),
+ REG(CP_SCRATCH_REG3, reg_dump_scratch),
+ REG(CP_SCRATCH_REG4, reg_dump_scratch),
+ REG(CP_SCRATCH_REG5, reg_dump_scratch),
+ REG(CP_SCRATCH_REG6, reg_dump_scratch),
+ REG(CP_SCRATCH_REG7, reg_dump_scratch),
+ {NULL},
}, reg_a3xx[] = {
- REG(CP_SCRATCH_REG0, reg_dump_scratch),
- REG(CP_SCRATCH_REG1, reg_dump_scratch),
- REG(CP_SCRATCH_REG2, reg_dump_scratch),
- REG(CP_SCRATCH_REG3, reg_dump_scratch),
- REG(CP_SCRATCH_REG4, reg_dump_scratch),
- REG(CP_SCRATCH_REG5, reg_dump_scratch),
- REG(CP_SCRATCH_REG6, reg_dump_scratch),
- REG(CP_SCRATCH_REG7, reg_dump_scratch),
- REG(VSC_SIZE_ADDRESS, reg_dump_gpuaddr),
- REG(SP_VS_PVT_MEM_ADDR_REG, reg_dump_gpuaddr),
- REG(SP_FS_PVT_MEM_ADDR_REG, reg_dump_gpuaddr),
- REG(SP_VS_OBJ_START_REG, reg_disasm_gpuaddr),
- REG(SP_FS_OBJ_START_REG, reg_disasm_gpuaddr),
- REG(TPL1_TP_FS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- {NULL},
+ REG(CP_SCRATCH_REG0, reg_dump_scratch),
+ REG(CP_SCRATCH_REG1, reg_dump_scratch),
+ REG(CP_SCRATCH_REG2, reg_dump_scratch),
+ REG(CP_SCRATCH_REG3, reg_dump_scratch),
+ REG(CP_SCRATCH_REG4, reg_dump_scratch),
+ REG(CP_SCRATCH_REG5, reg_dump_scratch),
+ REG(CP_SCRATCH_REG6, reg_dump_scratch),
+ REG(CP_SCRATCH_REG7, reg_dump_scratch),
+ REG(VSC_SIZE_ADDRESS, reg_dump_gpuaddr),
+ REG(SP_VS_PVT_MEM_ADDR_REG, reg_dump_gpuaddr),
+ REG(SP_FS_PVT_MEM_ADDR_REG, reg_dump_gpuaddr),
+ REG(SP_VS_OBJ_START_REG, reg_disasm_gpuaddr),
+ REG(SP_FS_OBJ_START_REG, reg_disasm_gpuaddr),
+ REG(TPL1_TP_FS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ {NULL},
}, reg_a4xx[] = {
- REG(CP_SCRATCH[0].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x1].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x2].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x3].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
- REG(SP_VS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_FS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_GS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_HS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_DS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_CS_PVT_MEM_ADDR, reg_dump_gpuaddr),
- REG(SP_VS_OBJ_START, reg_disasm_gpuaddr),
- REG(SP_FS_OBJ_START, reg_disasm_gpuaddr),
- REG(SP_GS_OBJ_START, reg_disasm_gpuaddr),
- REG(SP_HS_OBJ_START, reg_disasm_gpuaddr),
- REG(SP_DS_OBJ_START, reg_disasm_gpuaddr),
- REG(SP_CS_OBJ_START, reg_disasm_gpuaddr),
- REG(TPL1_TP_VS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- REG(TPL1_TP_HS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- REG(TPL1_TP_DS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- REG(TPL1_TP_GS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- REG(TPL1_TP_FS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
- {NULL},
+ REG(CP_SCRATCH[0].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x1].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x2].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x3].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
+ REG(SP_VS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_FS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_GS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_HS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_DS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_CS_PVT_MEM_ADDR, reg_dump_gpuaddr),
+ REG(SP_VS_OBJ_START, reg_disasm_gpuaddr),
+ REG(SP_FS_OBJ_START, reg_disasm_gpuaddr),
+ REG(SP_GS_OBJ_START, reg_disasm_gpuaddr),
+ REG(SP_HS_OBJ_START, reg_disasm_gpuaddr),
+ REG(SP_DS_OBJ_START, reg_disasm_gpuaddr),
+ REG(SP_CS_OBJ_START, reg_disasm_gpuaddr),
+ REG(TPL1_TP_VS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ REG(TPL1_TP_HS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ REG(TPL1_TP_DS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ REG(TPL1_TP_GS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ REG(TPL1_TP_FS_BORDER_COLOR_BASE_ADDR, reg_dump_gpuaddr),
+ {NULL},
}, reg_a5xx[] = {
- REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
- REG(SP_VS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_VS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(SP_HS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_HS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(SP_DS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_DS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(SP_GS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_GS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(SP_FS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_FS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(SP_CS_OBJ_START_LO, reg_gpuaddr_lo),
- REG(SP_CS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
- REG(TPL1_VS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_VS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_VS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_VS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_HS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_HS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_HS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_HS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_DS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_DS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_DS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_DS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_GS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_GS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_GS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_GS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_FS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_FS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_FS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_FS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_CS_TEX_CONST_LO, reg_gpuaddr_lo),
- REG(TPL1_CS_TEX_CONST_HI, reg_dump_tex_const_hi),
- REG(TPL1_CS_TEX_SAMP_LO, reg_gpuaddr_lo),
- REG(TPL1_CS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
- REG(TPL1_TP_BORDER_COLOR_BASE_ADDR_LO, reg_gpuaddr_lo),
- REG(TPL1_TP_BORDER_COLOR_BASE_ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[0].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[0].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[1].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[1].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[2].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[2].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[3].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[3].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[4].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[4].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[5].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[5].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[6].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[6].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT_FLAG_BUFFER[7].ADDR_LO, reg_gpuaddr_lo),
-// REG(RB_MRT_FLAG_BUFFER[7].ADDR_HI, reg_dump_gpuaddr_hi),
-// REG(RB_BLIT_FLAG_DST_LO, reg_gpuaddr_lo),
-// REG(RB_BLIT_FLAG_DST_HI, reg_dump_gpuaddr_hi),
-// REG(RB_MRT[0].BASE_LO, reg_gpuaddr_lo),
-// REG(RB_MRT[0].BASE_HI, reg_dump_gpuaddr_hi),
-// REG(RB_DEPTH_BUFFER_BASE_LO, reg_gpuaddr_lo),
-// REG(RB_DEPTH_BUFFER_BASE_HI, reg_dump_gpuaddr_hi),
-// REG(RB_DEPTH_FLAG_BUFFER_BASE_LO, reg_gpuaddr_lo),
-// REG(RB_DEPTH_FLAG_BUFFER_BASE_HI, reg_dump_gpuaddr_hi),
-// REG(RB_BLIT_DST_LO, reg_gpuaddr_lo),
-// REG(RB_BLIT_DST_HI, reg_dump_gpuaddr_hi),
-
-// REG(RB_2D_SRC_LO, reg_gpuaddr_lo),
-// REG(RB_2D_SRC_HI, reg_dump_gpuaddr_hi),
-// REG(RB_2D_SRC_FLAGS_LO, reg_gpuaddr_lo),
-// REG(RB_2D_SRC_FLAGS_HI, reg_dump_gpuaddr_hi),
-// REG(RB_2D_DST_LO, reg_gpuaddr_lo),
-// REG(RB_2D_DST_HI, reg_dump_gpuaddr_hi),
-// REG(RB_2D_DST_FLAGS_LO, reg_gpuaddr_lo),
-// REG(RB_2D_DST_FLAGS_HI, reg_dump_gpuaddr_hi),
-
- {NULL},
+ REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
+ REG(SP_VS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_VS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(SP_HS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_HS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(SP_DS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_DS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(SP_GS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_GS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(SP_FS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_FS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(SP_CS_OBJ_START_LO, reg_gpuaddr_lo),
+ REG(SP_CS_OBJ_START_HI, reg_disasm_gpuaddr_hi),
+ REG(TPL1_VS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_VS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_VS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_VS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_HS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_HS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_HS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_HS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_DS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_DS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_DS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_DS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_GS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_GS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_GS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_GS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_FS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_FS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_FS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_FS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_CS_TEX_CONST_LO, reg_gpuaddr_lo),
+ REG(TPL1_CS_TEX_CONST_HI, reg_dump_tex_const_hi),
+ REG(TPL1_CS_TEX_SAMP_LO, reg_gpuaddr_lo),
+ REG(TPL1_CS_TEX_SAMP_HI, reg_dump_tex_samp_hi),
+ REG(TPL1_TP_BORDER_COLOR_BASE_ADDR_LO, reg_gpuaddr_lo),
+ REG(TPL1_TP_BORDER_COLOR_BASE_ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[0].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[0].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[1].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[1].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[2].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[2].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[3].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[3].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[4].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[4].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[5].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[5].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[6].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[6].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT_FLAG_BUFFER[7].ADDR_LO, reg_gpuaddr_lo),
+// REG(RB_MRT_FLAG_BUFFER[7].ADDR_HI, reg_dump_gpuaddr_hi),
+// REG(RB_BLIT_FLAG_DST_LO, reg_gpuaddr_lo),
+// REG(RB_BLIT_FLAG_DST_HI, reg_dump_gpuaddr_hi),
+// REG(RB_MRT[0].BASE_LO, reg_gpuaddr_lo),
+// REG(RB_MRT[0].BASE_HI, reg_dump_gpuaddr_hi),
+// REG(RB_DEPTH_BUFFER_BASE_LO, reg_gpuaddr_lo),
+// REG(RB_DEPTH_BUFFER_BASE_HI, reg_dump_gpuaddr_hi),
+// REG(RB_DEPTH_FLAG_BUFFER_BASE_LO, reg_gpuaddr_lo),
+// REG(RB_DEPTH_FLAG_BUFFER_BASE_HI, reg_dump_gpuaddr_hi),
+// REG(RB_BLIT_DST_LO, reg_gpuaddr_lo),
+// REG(RB_BLIT_DST_HI, reg_dump_gpuaddr_hi),
+
+// REG(RB_2D_SRC_LO, reg_gpuaddr_lo),
+// REG(RB_2D_SRC_HI, reg_dump_gpuaddr_hi),
+// REG(RB_2D_SRC_FLAGS_LO, reg_gpuaddr_lo),
+// REG(RB_2D_SRC_FLAGS_HI, reg_dump_gpuaddr_hi),
+// REG(RB_2D_DST_LO, reg_gpuaddr_lo),
+// REG(RB_2D_DST_HI, reg_dump_gpuaddr_hi),
+// REG(RB_2D_DST_FLAGS_LO, reg_gpuaddr_lo),
+// REG(RB_2D_DST_FLAGS_HI, reg_dump_gpuaddr_hi),
+
+ {NULL},
}, reg_a6xx[] = {
- REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
- REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
-
- REG64(SP_VS_OBJ_START, reg_disasm_gpuaddr64),
- REG64(SP_HS_OBJ_START, reg_disasm_gpuaddr64),
- REG64(SP_DS_OBJ_START, reg_disasm_gpuaddr64),
- REG64(SP_GS_OBJ_START, reg_disasm_gpuaddr64),
- REG64(SP_FS_OBJ_START, reg_disasm_gpuaddr64),
- REG64(SP_CS_OBJ_START, reg_disasm_gpuaddr64),
-
- REG64(SP_VS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_VS_TEX_SAMP, reg_dump_gpuaddr64),
- REG64(SP_HS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_HS_TEX_SAMP, reg_dump_gpuaddr64),
- REG64(SP_DS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_DS_TEX_SAMP, reg_dump_gpuaddr64),
- REG64(SP_GS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_GS_TEX_SAMP, reg_dump_gpuaddr64),
- REG64(SP_FS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_FS_TEX_SAMP, reg_dump_gpuaddr64),
- REG64(SP_CS_TEX_CONST, reg_dump_gpuaddr64),
- REG64(SP_CS_TEX_SAMP, reg_dump_gpuaddr64),
-
- {NULL},
+ REG(CP_SCRATCH[0x4].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x5].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x6].REG, reg_dump_scratch),
+ REG(CP_SCRATCH[0x7].REG, reg_dump_scratch),
+
+ REG64(SP_VS_OBJ_START, reg_disasm_gpuaddr64),
+ REG64(SP_HS_OBJ_START, reg_disasm_gpuaddr64),
+ REG64(SP_DS_OBJ_START, reg_disasm_gpuaddr64),
+ REG64(SP_GS_OBJ_START, reg_disasm_gpuaddr64),
+ REG64(SP_FS_OBJ_START, reg_disasm_gpuaddr64),
+ REG64(SP_CS_OBJ_START, reg_disasm_gpuaddr64),
+
+ REG64(SP_VS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_VS_TEX_SAMP, reg_dump_gpuaddr64),
+ REG64(SP_HS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_HS_TEX_SAMP, reg_dump_gpuaddr64),
+ REG64(SP_DS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_DS_TEX_SAMP, reg_dump_gpuaddr64),
+ REG64(SP_GS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_GS_TEX_SAMP, reg_dump_gpuaddr64),
+ REG64(SP_FS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_FS_TEX_SAMP, reg_dump_gpuaddr64),
+ REG64(SP_CS_TEX_CONST, reg_dump_gpuaddr64),
+ REG64(SP_CS_TEX_SAMP, reg_dump_gpuaddr64),
+
+ {NULL},
}, *type0_reg;
static struct rnn *rnn;
@@ -705,266 +713,262 @@ static struct rnn *rnn;
static void
init_rnn(const char *gpuname)
{
- rnn = rnn_new(!options->color);
+ rnn = rnn_new(!options->color);
- rnn_load(rnn, gpuname);
+ rnn_load(rnn, gpuname);
- if (options->querystrs) {
- int i;
- queryvals = calloc(options->nquery, sizeof(queryvals[0]));
+ if (options->querystrs) {
+ int i;
+ queryvals = calloc(options->nquery, sizeof(queryvals[0]));
- for (i = 0; i < options->nquery; i++) {
- int val = strtol(options->querystrs[i], NULL, 0);
+ for (i = 0; i < options->nquery; i++) {
+ int val = strtol(options->querystrs[i], NULL, 0);
- if (val == 0)
- val = regbase(options->querystrs[i]);
+ if (val == 0)
+ val = regbase(options->querystrs[i]);
- queryvals[i] = val;
- printf("querystr: %s -> 0x%x\n", options->querystrs[i], queryvals[i]);
- }
- }
+ queryvals[i] = val;
+ printf("querystr: %s -> 0x%x\n", options->querystrs[i], queryvals[i]);
+ }
+ }
- for (unsigned idx = 0; type0_reg[idx].regname; idx++) {
- type0_reg[idx].regbase = regbase(type0_reg[idx].regname);
- if (!type0_reg[idx].regbase) {
- printf("invalid register name: %s\n", type0_reg[idx].regname);
- exit(1);
- }
- }
+ for (unsigned idx = 0; type0_reg[idx].regname; idx++) {
+ type0_reg[idx].regbase = regbase(type0_reg[idx].regname);
+ if (!type0_reg[idx].regbase) {
+ printf("invalid register name: %s\n", type0_reg[idx].regname);
+ exit(1);
+ }
+ }
}
void
reset_regs(void)
{
- clear_written();
- clear_lastvals();
- memset(&ibs, 0, sizeof(ibs));
+ clear_written();
+ clear_lastvals();
+ memset(&ibs, 0, sizeof(ibs));
}
void
cffdec_init(const struct cffdec_options *_options)
{
- options = _options;
- summary = options->summary;
-
- /* in case we're decoding multiple files: */
- free(queryvals);
- reset_regs();
- draw_count = 0;
-
- /* TODO we need an API to free/cleanup any previous rnn */
-
- switch (options->gpu_id) {
- case 200 ... 299:
- type0_reg = reg_a2xx;
- init_rnn("a2xx");
- break;
- case 300 ... 399:
- type0_reg = reg_a3xx;
- init_rnn("a3xx");
- break;
- case 400 ... 499:
- type0_reg = reg_a4xx;
- init_rnn("a4xx");
- break;
- case 500 ... 599:
- type0_reg = reg_a5xx;
- init_rnn("a5xx");
- break;
- case 600 ... 699:
- type0_reg = reg_a6xx;
- init_rnn("a6xx");
- break;
- default:
- errx(-1, "unsupported gpu");
- }
+ options = _options;
+ summary = options->summary;
+
+ /* in case we're decoding multiple files: */
+ free(queryvals);
+ reset_regs();
+ draw_count = 0;
+
+ /* TODO we need an API to free/cleanup any previous rnn */
+
+ switch (options->gpu_id) {
+ case 200 ... 299:
+ type0_reg = reg_a2xx;
+ init_rnn("a2xx");
+ break;
+ case 300 ... 399:
+ type0_reg = reg_a3xx;
+ init_rnn("a3xx");
+ break;
+ case 400 ... 499:
+ type0_reg = reg_a4xx;
+ init_rnn("a4xx");
+ break;
+ case 500 ... 599:
+ type0_reg = reg_a5xx;
+ init_rnn("a5xx");
+ break;
+ case 600 ... 699:
+ type0_reg = reg_a6xx;
+ init_rnn("a6xx");
+ break;
+ default:
+ errx(-1, "unsupported gpu");
+ }
}
const char *
pktname(unsigned opc)
{
- return rnn_enumname(rnn, "adreno_pm4_type3_packets", opc);
+ return rnn_enumname(rnn, "adreno_pm4_type3_packets", opc);
}
const char *
regname(uint32_t regbase, int color)
{
- return rnn_regname(rnn, regbase, color);
+ return rnn_regname(rnn, regbase, color);
}
uint32_t
regbase(const char *name)
{
- return rnn_regbase(rnn, name);
+ return rnn_regbase(rnn, name);
}
static int
endswith(uint32_t regbase, const char *suffix)
{
- const char *name = regname(regbase, 0);
- const char *s = strstr(name, suffix);
- if (!s)
- return 0;
- return (s - strlen(name) + strlen(suffix)) == name;
+ const char *name = regname(regbase, 0);
+ const char *s = strstr(name, suffix);
+ if (!s)
+ return 0;
+ return (s - strlen(name) + strlen(suffix)) == name;
}
void
dump_register_val(uint32_t regbase, uint32_t dword, int level)
{
- struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
-
- if (info && info->typeinfo) {
- uint64_t gpuaddr = 0;
- char *decoded = rnndec_decodeval(rnn->vc, info->typeinfo, dword);
- printf("%s%s: %s", levels[level], info->name, decoded);
-
- /* Try and figure out if we are looking at a gpuaddr.. this
- * might be useful for other gen's too, but at least a5xx has
- * the _HI/_LO suffix we can look for. Maybe a better approach
- * would be some special annotation in the xml..
- * for a6xx use "address" and "waddress" types
- *
- */
- if (options->gpu_id >= 600) {
- if (!strcmp(info->typeinfo->name, "address") ||
- !strcmp(info->typeinfo->name, "waddress")) {
- gpuaddr = (((uint64_t)reg_val(regbase+1)) << 32) | dword;
- }
- } else if (options->gpu_id >= 500) {
- if (endswith(regbase, "_HI") && endswith(regbase-1, "_LO")) {
- gpuaddr = (((uint64_t)dword) << 32) | reg_val(regbase-1);
- } else if (endswith(regbase, "_LO") && endswith(regbase+1, "_HI")) {
- gpuaddr = (((uint64_t)reg_val(regbase+1)) << 32) | dword;
- }
- }
-
- if (gpuaddr && hostptr(gpuaddr)) {
- printf("\t\tbase=%"PRIx64", offset=%"PRIu64", size=%u",
- gpubaseaddr(gpuaddr),
- gpuaddr - gpubaseaddr(gpuaddr),
- hostlen(gpubaseaddr(gpuaddr)));
- }
-
- printf("\n");
-
- free(decoded);
- } else if (info) {
- printf("%s%s: %08x\n", levels[level], info->name, dword);
- } else {
- printf("%s<%04x>: %08x\n", levels[level], regbase, dword);
- }
-
- if (info) {
- free(info->name);
- free(info);
- }
+ struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
+
+ if (info && info->typeinfo) {
+ uint64_t gpuaddr = 0;
+ char *decoded = rnndec_decodeval(rnn->vc, info->typeinfo, dword);
+ printf("%s%s: %s", levels[level], info->name, decoded);
+
+ /* Try and figure out if we are looking at a gpuaddr.. this
+ * might be useful for other gen's too, but at least a5xx has
+ * the _HI/_LO suffix we can look for. Maybe a better approach
+ * would be some special annotation in the xml..
+ * for a6xx use "address" and "waddress" types
+ */
+ if (options->gpu_id >= 600) {
+ if (!strcmp(info->typeinfo->name, "address") ||
+ !strcmp(info->typeinfo->name, "waddress")) {
+ gpuaddr = (((uint64_t)reg_val(regbase + 1)) << 32) | dword;
+ }
+ } else if (options->gpu_id >= 500) {
+ if (endswith(regbase, "_HI") && endswith(regbase - 1, "_LO")) {
+ gpuaddr = (((uint64_t)dword) << 32) | reg_val(regbase - 1);
+ } else if (endswith(regbase, "_LO") && endswith(regbase + 1, "_HI")) {
+ gpuaddr = (((uint64_t)reg_val(regbase + 1)) << 32) | dword;
+ }
+ }
+
+ if (gpuaddr && hostptr(gpuaddr)) {
+ printf("\t\tbase=%" PRIx64 ", offset=%" PRIu64 ", size=%u",
+ gpubaseaddr(gpuaddr), gpuaddr - gpubaseaddr(gpuaddr),
+ hostlen(gpubaseaddr(gpuaddr)));
+ }
+
+ printf("\n");
+
+ free(decoded);
+ } else if (info) {
+ printf("%s%s: %08x\n", levels[level], info->name, dword);
+ } else {
+ printf("%s<%04x>: %08x\n", levels[level], regbase, dword);
+ }
+
+ if (info) {
+ free(info->name);
+ free(info);
+ }
}
static void
dump_register(uint32_t regbase, uint32_t dword, int level)
{
- if (!quiet(3)) {
- dump_register_val(regbase, dword, level);
- }
+ if (!quiet(3)) {
+ dump_register_val(regbase, dword, level);
+ }
- for (unsigned idx = 0; type0_reg[idx].regname; idx++) {
- if (type0_reg[idx].regbase == regbase) {
- if (type0_reg[idx].is_reg64) {
- uint64_t qword = (((uint64_t)reg_val(regbase+1)) << 32) | dword;
- type0_reg[idx].fxn64(type0_reg[idx].regname, qword, level);
- } else {
- type0_reg[idx].fxn(type0_reg[idx].regname, dword, level);
- }
- break;
- }
- }
+ for (unsigned idx = 0; type0_reg[idx].regname; idx++) {
+ if (type0_reg[idx].regbase == regbase) {
+ if (type0_reg[idx].is_reg64) {
+ uint64_t qword = (((uint64_t)reg_val(regbase + 1)) << 32) | dword;
+ type0_reg[idx].fxn64(type0_reg[idx].regname, qword, level);
+ } else {
+ type0_reg[idx].fxn(type0_reg[idx].regname, dword, level);
+ }
+ break;
+ }
+ }
}
static bool
is_banked_reg(uint32_t regbase)
{
- return (0x2000 <= regbase) && (regbase < 0x2400);
+ return (0x2000 <= regbase) && (regbase < 0x2400);
}
static void
-dump_registers(uint32_t regbase, uint32_t *dwords, uint32_t sizedwords, int level)
+dump_registers(uint32_t regbase, uint32_t *dwords, uint32_t sizedwords,
+ int level)
{
- while (sizedwords--) {
- int last_summary = summary;
+ while (sizedwords--) {
+ int last_summary = summary;
- /* access to non-banked registers needs a WFI:
- * TODO banked register range for a2xx??
- */
- if (needs_wfi && !is_banked_reg(regbase))
- printl(2, "NEEDS WFI: %s (%x)\n", regname(regbase, 1), regbase);
+ /* access to non-banked registers needs a WFI:
+ * TODO banked register range for a2xx??
+ */
+ if (needs_wfi && !is_banked_reg(regbase))
+ printl(2, "NEEDS WFI: %s (%x)\n", regname(regbase, 1), regbase);
- reg_set(regbase, *dwords);
- dump_register(regbase, *dwords, level);
- regbase++;
- dwords++;
- summary = last_summary;
- }
+ reg_set(regbase, *dwords);
+ dump_register(regbase, *dwords, level);
+ regbase++;
+ dwords++;
+ summary = last_summary;
+ }
}
static void
-dump_domain(uint32_t *dwords, uint32_t sizedwords, int level,
- const char *name)
+dump_domain(uint32_t *dwords, uint32_t sizedwords, int level, const char *name)
{
- struct rnndomain *dom;
- int i;
+ struct rnndomain *dom;
+ int i;
- dom = rnn_finddomain(rnn->db, name);
+ dom = rnn_finddomain(rnn->db, name);
- if (!dom)
- return;
+ if (!dom)
+ return;
- if (script_packet)
- script_packet(dwords, sizedwords, rnn, dom);
+ if (script_packet)
+ script_packet(dwords, sizedwords, rnn, dom);
- if (quiet(2))
- return;
+ if (quiet(2))
+ return;
- for (i = 0; i < sizedwords; i++) {
- struct rnndecaddrinfo *info = rnndec_decodeaddr(rnn->vc, dom, i, 0);
- char *decoded;
- if (!(info && info->typeinfo))
- break;
- uint64_t value = dwords[i];
- if (info->typeinfo->high >= 32 && i < sizedwords - 1) {
- value |= (uint64_t) dwords[i + 1] << 32;
- i++; /* skip the next dword since we're printing it now */
- }
- decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value);
- /* Unlike the register printing path, we don't print the name
- * of the register, so if it doesn't contain other named
- * things (i.e. it isn't a bitset) then print the register
- * name as if it's a bitset with a single entry. This avoids
- * having to create a dummy register with a single entry to
- * get a name in the decoding.
- */
- if (info->typeinfo->type == RNN_TTYPE_BITSET ||
- info->typeinfo->type == RNN_TTYPE_INLINE_BITSET) {
- printf("%s%s\n", levels[level], decoded);
- } else {
- printf("%s{ %s%s%s = %s }\n", levels[level],
- rnn->vc->colors->rname, info->name,
- rnn->vc->colors->reset, decoded);
- }
- free(decoded);
- free(info->name);
- free(info);
- }
+ for (i = 0; i < sizedwords; i++) {
+ struct rnndecaddrinfo *info = rnndec_decodeaddr(rnn->vc, dom, i, 0);
+ char *decoded;
+ if (!(info && info->typeinfo))
+ break;
+ uint64_t value = dwords[i];
+ if (info->typeinfo->high >= 32 && i < sizedwords - 1) {
+ value |= (uint64_t)dwords[i + 1] << 32;
+ i++; /* skip the next dword since we're printing it now */
+ }
+ decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value);
+ /* Unlike the register printing path, we don't print the name
+ * of the register, so if it doesn't contain other named
+ * things (i.e. it isn't a bitset) then print the register
+ * name as if it's a bitset with a single entry. This avoids
+ * having to create a dummy register with a single entry to
+ * get a name in the decoding.
+ */
+ if (info->typeinfo->type == RNN_TTYPE_BITSET ||
+ info->typeinfo->type == RNN_TTYPE_INLINE_BITSET) {
+ printf("%s%s\n", levels[level], decoded);
+ } else {
+ printf("%s{ %s%s%s = %s }\n", levels[level], rnn->vc->colors->rname,
+ info->name, rnn->vc->colors->reset, decoded);
+ }
+ free(decoded);
+ free(info->name);
+ free(info);
+ }
}
-
static uint32_t bin_x1, bin_x2, bin_y1, bin_y2;
static unsigned mode;
static const char *render_mode;
static enum {
- MODE_BINNING = 0x1,
- MODE_GMEM = 0x2,
- MODE_BYPASS = 0x4,
- MODE_ALL = MODE_BINNING | MODE_GMEM | MODE_BYPASS,
+ MODE_BINNING = 0x1,
+ MODE_GMEM = 0x2,
+ MODE_BYPASS = 0x4,
+ MODE_ALL = MODE_BINNING | MODE_GMEM | MODE_BYPASS,
} enable_mask = MODE_ALL;
static bool skip_ib2_enable_global;
static bool skip_ib2_enable_local;
@@ -972,130 +976,131 @@ static bool skip_ib2_enable_local;
static void
print_mode(int level)
{
- if ((options->gpu_id >= 500) && !quiet(2)) {
- printf("%smode: %s\n", levels[level], render_mode);
- printf("%sskip_ib2: g=%d, l=%d\n", levels[level], skip_ib2_enable_global, skip_ib2_enable_local);
- }
+ if ((options->gpu_id >= 500) && !quiet(2)) {
+ printf("%smode: %s\n", levels[level], render_mode);
+ printf("%sskip_ib2: g=%d, l=%d\n", levels[level], skip_ib2_enable_global,
+ skip_ib2_enable_local);
+ }
}
static bool
skip_query(void)
{
- switch (options->query_mode) {
- case QUERY_ALL:
- /* never skip: */
- return false;
- case QUERY_WRITTEN:
- for (int i = 0; i < options->nquery; i++) {
- uint32_t regbase = queryvals[i];
- if (!reg_written(regbase)) {
- continue;
- }
- if (reg_rewritten(regbase)) {
- return false;
- }
- }
- return true;
- case QUERY_DELTA:
- for (int i = 0; i < options->nquery; i++) {
- uint32_t regbase = queryvals[i];
- if (!reg_written(regbase)) {
- continue;
- }
- uint32_t lastval = reg_val(regbase);
- if (lastval != lastvals[regbase]) {
- return false;
- }
- }
- return true;
- }
- return true;
+ switch (options->query_mode) {
+ case QUERY_ALL:
+ /* never skip: */
+ return false;
+ case QUERY_WRITTEN:
+ for (int i = 0; i < options->nquery; i++) {
+ uint32_t regbase = queryvals[i];
+ if (!reg_written(regbase)) {
+ continue;
+ }
+ if (reg_rewritten(regbase)) {
+ return false;
+ }
+ }
+ return true;
+ case QUERY_DELTA:
+ for (int i = 0; i < options->nquery; i++) {
+ uint32_t regbase = queryvals[i];
+ if (!reg_written(regbase)) {
+ continue;
+ }
+ uint32_t lastval = reg_val(regbase);
+ if (lastval != lastvals[regbase]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return true;
}
static void
__do_query(const char *primtype, uint32_t num_indices)
{
- int n = 0;
-
- if ((500 <= options->gpu_id) && (options->gpu_id < 700)) {
- uint32_t scissor_tl = reg_val(regbase("GRAS_SC_WINDOW_SCISSOR_TL"));
- uint32_t scissor_br = reg_val(regbase("GRAS_SC_WINDOW_SCISSOR_BR"));
-
- bin_x1 = scissor_tl & 0xffff;
- bin_y1 = scissor_tl >> 16;
- bin_x2 = scissor_br & 0xffff;
- bin_y2 = scissor_br >> 16;
- }
-
- for (int i = 0; i < options->nquery; i++) {
- uint32_t regbase = queryvals[i];
- if (reg_written(regbase)) {
- uint32_t lastval = reg_val(regbase);
- printf("%4d: %s(%u,%u-%u,%u):%u:", draw_count, primtype,
- bin_x1, bin_y1, bin_x2, bin_y2, num_indices);
- if (options->gpu_id >= 500)
- printf("%s:", render_mode);
- printf("\t%08x", lastval);
- if (lastval != lastvals[regbase]) {
- printf("!");
- } else {
- printf(" ");
- }
- if (reg_rewritten(regbase)) {
- printf("+");
- } else {
- printf(" ");
- }
- dump_register_val(regbase, lastval, 0);
- n++;
- }
- }
-
- if (n > 1)
- printf("\n");
+ int n = 0;
+
+ if ((500 <= options->gpu_id) && (options->gpu_id < 700)) {
+ uint32_t scissor_tl = reg_val(regbase("GRAS_SC_WINDOW_SCISSOR_TL"));
+ uint32_t scissor_br = reg_val(regbase("GRAS_SC_WINDOW_SCISSOR_BR"));
+
+ bin_x1 = scissor_tl & 0xffff;
+ bin_y1 = scissor_tl >> 16;
+ bin_x2 = scissor_br & 0xffff;
+ bin_y2 = scissor_br >> 16;
+ }
+
+ for (int i = 0; i < options->nquery; i++) {
+ uint32_t regbase = queryvals[i];
+ if (reg_written(regbase)) {
+ uint32_t lastval = reg_val(regbase);
+ printf("%4d: %s(%u,%u-%u,%u):%u:", draw_count, primtype, bin_x1,
+ bin_y1, bin_x2, bin_y2, num_indices);
+ if (options->gpu_id >= 500)
+ printf("%s:", render_mode);
+ printf("\t%08x", lastval);
+ if (lastval != lastvals[regbase]) {
+ printf("!");
+ } else {
+ printf(" ");
+ }
+ if (reg_rewritten(regbase)) {
+ printf("+");
+ } else {
+ printf(" ");
+ }
+ dump_register_val(regbase, lastval, 0);
+ n++;
+ }
+ }
+
+ if (n > 1)
+ printf("\n");
}
static void
do_query_compare(const char *primtype, uint32_t num_indices)
{
- unsigned saved_enable_mask = enable_mask;
- const char *saved_render_mode = render_mode;
+ unsigned saved_enable_mask = enable_mask;
+ const char *saved_render_mode = render_mode;
- /* in 'query-compare' mode, we want to see if the register is writtten
- * or changed in any mode:
- *
- * (NOTE: this could cause false-positive for 'query-delta' if the reg
- * is written with different values in binning vs sysmem/gmem mode, as
- * we don't track previous values per-mode, but I think we can live with
- * that)
- */
- enable_mask = MODE_ALL;
+ /* in 'query-compare' mode, we want to see if the register is writtten
+ * or changed in any mode:
+ *
+ * (NOTE: this could cause false-positive for 'query-delta' if the reg
+ * is written with different values in binning vs sysmem/gmem mode, as
+ * we don't track previous values per-mode, but I think we can live with
+ * that)
+ */
+ enable_mask = MODE_ALL;
- clear_rewritten();
- load_all_groups(0);
+ clear_rewritten();
+ load_all_groups(0);
- if (!skip_query()) {
- /* dump binning pass values: */
- enable_mask = MODE_BINNING;
- render_mode = "BINNING";
- clear_rewritten();
- load_all_groups(0);
- __do_query(primtype, num_indices);
+ if (!skip_query()) {
+ /* dump binning pass values: */
+ enable_mask = MODE_BINNING;
+ render_mode = "BINNING";
+ clear_rewritten();
+ load_all_groups(0);
+ __do_query(primtype, num_indices);
- /* dump draw pass values: */
- enable_mask = MODE_GMEM | MODE_BYPASS;
- render_mode = "DRAW";
- clear_rewritten();
- load_all_groups(0);
- __do_query(primtype, num_indices);
+ /* dump draw pass values: */
+ enable_mask = MODE_GMEM | MODE_BYPASS;
+ render_mode = "DRAW";
+ clear_rewritten();
+ load_all_groups(0);
+ __do_query(primtype, num_indices);
- printf("\n");
- }
+ printf("\n");
+ }
- enable_mask = saved_enable_mask;
- render_mode = saved_render_mode;
+ enable_mask = saved_enable_mask;
+ render_mode = saved_render_mode;
- disable_all_groups();
+ disable_all_groups();
}
/* well, actually query and script..
@@ -1104,94 +1109,95 @@ do_query_compare(const char *primtype, uint32_t num_indices)
static void
do_query(const char *primtype, uint32_t num_indices)
{
- if (script_draw)
- script_draw(primtype, num_indices);
+ if (script_draw)
+ script_draw(primtype, num_indices);
- if (options->query_compare) {
- do_query_compare(primtype, num_indices);
- return;
- }
+ if (options->query_compare) {
+ do_query_compare(primtype, num_indices);
+ return;
+ }
- if (skip_query())
- return;
+ if (skip_query())
+ return;
- __do_query(primtype, num_indices);
+ __do_query(primtype, num_indices);
}
static void
cp_im_loadi(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t start = dwords[1] >> 16;
- uint32_t size = dwords[1] & 0xffff;
- const char *type = NULL, *ext = NULL;
- gl_shader_stage disasm_type;
-
- switch (dwords[0]) {
- case 0:
- type = "vertex";
- ext = "vo";
- disasm_type = MESA_SHADER_VERTEX;
- break;
- case 1:
- type = "fragment";
- ext = "fo";
- disasm_type = MESA_SHADER_FRAGMENT;
- break;
- default:
- type = "<unknown>";
- disasm_type = 0;
- break;
- }
-
- printf("%s%s shader, start=%04x, size=%04x\n", levels[level], type, start, size);
- disasm_a2xx(dwords + 2, sizedwords - 2, level+2, disasm_type);
-
- /* dump raw shader: */
- if (ext)
- dump_shader(ext, dwords + 2, (sizedwords - 2) * 4);
+ uint32_t start = dwords[1] >> 16;
+ uint32_t size = dwords[1] & 0xffff;
+ const char *type = NULL, *ext = NULL;
+ gl_shader_stage disasm_type;
+
+ switch (dwords[0]) {
+ case 0:
+ type = "vertex";
+ ext = "vo";
+ disasm_type = MESA_SHADER_VERTEX;
+ break;
+ case 1:
+ type = "fragment";
+ ext = "fo";
+ disasm_type = MESA_SHADER_FRAGMENT;
+ break;
+ default:
+ type = "<unknown>";
+ disasm_type = 0;
+ break;
+ }
+
+ printf("%s%s shader, start=%04x, size=%04x\n", levels[level], type, start,
+ size);
+ disasm_a2xx(dwords + 2, sizedwords - 2, level + 2, disasm_type);
+
+ /* dump raw shader: */
+ if (ext)
+ dump_shader(ext, dwords + 2, (sizedwords - 2) * 4);
}
static void
cp_wide_reg_write(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t reg = dwords[0] & 0xffff;
- int i;
- for (i = 1; i < sizedwords; i++) {
- dump_register(reg, dwords[i], level+1);
- reg_set(reg, dwords[i]);
- reg++;
- }
+ uint32_t reg = dwords[0] & 0xffff;
+ int i;
+ for (i = 1; i < sizedwords; i++) {
+ dump_register(reg, dwords[i], level + 1);
+ reg_set(reg, dwords[i]);
+ reg++;
+ }
}
enum state_t {
- TEX_SAMP = 1,
- TEX_CONST,
- TEX_MIPADDR, /* a3xx only */
- SHADER_PROG,
- SHADER_CONST,
-
- // image/ssbo state:
- SSBO_0,
- SSBO_1,
- SSBO_2,
-
- UBO,
-
- // unknown things, just to hexdumps:
- UNKNOWN_DWORDS,
- UNKNOWN_2DWORDS,
- UNKNOWN_4DWORDS,
+ TEX_SAMP = 1,
+ TEX_CONST,
+ TEX_MIPADDR, /* a3xx only */
+ SHADER_PROG,
+ SHADER_CONST,
+
+ // image/ssbo state:
+ SSBO_0,
+ SSBO_1,
+ SSBO_2,
+
+ UBO,
+
+ // unknown things, just to hexdumps:
+ UNKNOWN_DWORDS,
+ UNKNOWN_2DWORDS,
+ UNKNOWN_4DWORDS,
};
enum adreno_state_block {
- SB_VERT_TEX = 0,
- SB_VERT_MIPADDR = 1,
- SB_FRAG_TEX = 2,
- SB_FRAG_MIPADDR = 3,
- SB_VERT_SHADER = 4,
- SB_GEOM_SHADER = 5,
- SB_FRAG_SHADER = 6,
- SB_COMPUTE_SHADER = 7,
+ SB_VERT_TEX = 0,
+ SB_VERT_MIPADDR = 1,
+ SB_FRAG_TEX = 2,
+ SB_FRAG_MIPADDR = 3,
+ SB_VERT_SHADER = 4,
+ SB_GEOM_SHADER = 5,
+ SB_FRAG_SHADER = 6,
+ SB_COMPUTE_SHADER = 7,
};
/* TODO there is probably a clever way to let rnndec parse things so
@@ -1199,595 +1205,606 @@ enum adreno_state_block {
*/
static void
-a3xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage, enum state_t *state,
- enum state_src_t *src)
-{
- unsigned state_block_id = (dwords[0] >> 19) & 0x7;
- unsigned state_type = dwords[1] & 0x3;
- static const struct {
- gl_shader_stage stage;
- enum state_t state;
- } lookup[0xf][0x3] = {
- [SB_VERT_TEX][0] = { MESA_SHADER_VERTEX, TEX_SAMP },
- [SB_VERT_TEX][1] = { MESA_SHADER_VERTEX, TEX_CONST },
- [SB_FRAG_TEX][0] = { MESA_SHADER_FRAGMENT, TEX_SAMP },
- [SB_FRAG_TEX][1] = { MESA_SHADER_FRAGMENT, TEX_CONST },
- [SB_VERT_SHADER][0] = { MESA_SHADER_VERTEX, SHADER_PROG },
- [SB_VERT_SHADER][1] = { MESA_SHADER_VERTEX, SHADER_CONST },
- [SB_FRAG_SHADER][0] = { MESA_SHADER_FRAGMENT, SHADER_PROG },
- [SB_FRAG_SHADER][1] = { MESA_SHADER_FRAGMENT, SHADER_CONST },
- };
-
- *stage = lookup[state_block_id][state_type].stage;
- *state = lookup[state_block_id][state_type].state;
- unsigned state_src = (dwords[0] >> 16) & 0x7;
- if (state_src == 0 /* SS_DIRECT */)
- *src = STATE_SRC_DIRECT;
- else
- *src = STATE_SRC_INDIRECT;
+a3xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage,
+ enum state_t *state, enum state_src_t *src)
+{
+ unsigned state_block_id = (dwords[0] >> 19) & 0x7;
+ unsigned state_type = dwords[1] & 0x3;
+ static const struct {
+ gl_shader_stage stage;
+ enum state_t state;
+ } lookup[0xf][0x3] = {
+ [SB_VERT_TEX][0] = {MESA_SHADER_VERTEX, TEX_SAMP},
+ [SB_VERT_TEX][1] = {MESA_SHADER_VERTEX, TEX_CONST},
+ [SB_FRAG_TEX][0] = {MESA_SHADER_FRAGMENT, TEX_SAMP},
+ [SB_FRAG_TEX][1] = {MESA_SHADER_FRAGMENT, TEX_CONST},
+ [SB_VERT_SHADER][0] = {MESA_SHADER_VERTEX, SHADER_PROG},
+ [SB_VERT_SHADER][1] = {MESA_SHADER_VERTEX, SHADER_CONST},
+ [SB_FRAG_SHADER][0] = {MESA_SHADER_FRAGMENT, SHADER_PROG},
+ [SB_FRAG_SHADER][1] = {MESA_SHADER_FRAGMENT, SHADER_CONST},
+ };
+
+ *stage = lookup[state_block_id][state_type].stage;
+ *state = lookup[state_block_id][state_type].state;
+ unsigned state_src = (dwords[0] >> 16) & 0x7;
+ if (state_src == 0 /* SS_DIRECT */)
+ *src = STATE_SRC_DIRECT;
+ else
+ *src = STATE_SRC_INDIRECT;
}
static enum state_src_t
_get_state_src(unsigned dword0)
{
- switch ((dword0 >> 16) & 0x3) {
- case 0: /* SS4_DIRECT / SS6_DIRECT */
- return STATE_SRC_DIRECT;
- case 2: /* SS4_INDIRECT / SS6_INDIRECT */
- return STATE_SRC_INDIRECT;
- case 1: /* SS6_BINDLESS */
- return STATE_SRC_BINDLESS;
- default:
- return STATE_SRC_DIRECT;
- }
+ switch ((dword0 >> 16) & 0x3) {
+ case 0: /* SS4_DIRECT / SS6_DIRECT */
+ return STATE_SRC_DIRECT;
+ case 2: /* SS4_INDIRECT / SS6_INDIRECT */
+ return STATE_SRC_INDIRECT;
+ case 1: /* SS6_BINDLESS */
+ return STATE_SRC_BINDLESS;
+ default:
+ return STATE_SRC_DIRECT;
+ }
}
static void
_get_state_type(unsigned state_block_id, unsigned state_type,
- gl_shader_stage *stage, enum state_t *state)
-{
- static const struct {
- gl_shader_stage stage;
- enum state_t state;
- } lookup[0x10][0x4] = {
- // SB4_VS_TEX:
- [0x0][0] = { MESA_SHADER_VERTEX, TEX_SAMP },
- [0x0][1] = { MESA_SHADER_VERTEX, TEX_CONST },
- [0x0][2] = { MESA_SHADER_VERTEX, UBO },
- // SB4_HS_TEX:
- [0x1][0] = { MESA_SHADER_TESS_CTRL, TEX_SAMP },
- [0x1][1] = { MESA_SHADER_TESS_CTRL, TEX_CONST },
- [0x1][2] = { MESA_SHADER_TESS_CTRL, UBO },
- // SB4_DS_TEX:
- [0x2][0] = { MESA_SHADER_TESS_EVAL, TEX_SAMP },
- [0x2][1] = { MESA_SHADER_TESS_EVAL, TEX_CONST },
- [0x2][2] = { MESA_SHADER_TESS_EVAL, UBO },
- // SB4_GS_TEX:
- [0x3][0] = { MESA_SHADER_GEOMETRY, TEX_SAMP },
- [0x3][1] = { MESA_SHADER_GEOMETRY, TEX_CONST },
- [0x3][2] = { MESA_SHADER_GEOMETRY, UBO },
- // SB4_FS_TEX:
- [0x4][0] = { MESA_SHADER_FRAGMENT, TEX_SAMP },
- [0x4][1] = { MESA_SHADER_FRAGMENT, TEX_CONST },
- [0x4][2] = { MESA_SHADER_FRAGMENT, UBO },
- // SB4_CS_TEX:
- [0x5][0] = { MESA_SHADER_COMPUTE, TEX_SAMP },
- [0x5][1] = { MESA_SHADER_COMPUTE, TEX_CONST },
- [0x5][2] = { MESA_SHADER_COMPUTE, UBO },
- // SB4_VS_SHADER:
- [0x8][0] = { MESA_SHADER_VERTEX, SHADER_PROG },
- [0x8][1] = { MESA_SHADER_VERTEX, SHADER_CONST },
- [0x8][2] = { MESA_SHADER_VERTEX, UBO },
- // SB4_HS_SHADER
- [0x9][0] = { MESA_SHADER_TESS_CTRL, SHADER_PROG },
- [0x9][1] = { MESA_SHADER_TESS_CTRL, SHADER_CONST },
- [0x9][2] = { MESA_SHADER_TESS_CTRL, UBO },
- // SB4_DS_SHADER
- [0xa][0] = { MESA_SHADER_TESS_EVAL, SHADER_PROG },
- [0xa][1] = { MESA_SHADER_TESS_EVAL, SHADER_CONST },
- [0xa][2] = { MESA_SHADER_TESS_EVAL, UBO },
- // SB4_GS_SHADER
- [0xb][0] = { MESA_SHADER_GEOMETRY, SHADER_PROG },
- [0xb][1] = { MESA_SHADER_GEOMETRY, SHADER_CONST },
- [0xb][2] = { MESA_SHADER_GEOMETRY, UBO },
- // SB4_FS_SHADER:
- [0xc][0] = { MESA_SHADER_FRAGMENT, SHADER_PROG },
- [0xc][1] = { MESA_SHADER_FRAGMENT, SHADER_CONST },
- [0xc][2] = { MESA_SHADER_FRAGMENT, UBO },
- // SB4_CS_SHADER:
- [0xd][0] = { MESA_SHADER_COMPUTE, SHADER_PROG },
- [0xd][1] = { MESA_SHADER_COMPUTE, SHADER_CONST },
- [0xd][2] = { MESA_SHADER_COMPUTE, UBO },
- [0xd][3] = { MESA_SHADER_COMPUTE, SSBO_0 }, /* a6xx location */
- // SB4_SSBO (shared across all stages)
- [0xe][0] = { 0, SSBO_0 }, /* a5xx (and a4xx?) location */
- [0xe][1] = { 0, SSBO_1 },
- [0xe][2] = { 0, SSBO_2 },
- // SB4_CS_SSBO
- [0xf][0] = { MESA_SHADER_COMPUTE, SSBO_0 },
- [0xf][1] = { MESA_SHADER_COMPUTE, SSBO_1 },
- [0xf][2] = { MESA_SHADER_COMPUTE, SSBO_2 },
- // unknown things
- /* This looks like combined UBO state for 3d stages (a5xx and
- * before?? I think a6xx has UBO state per shader stage:
- */
- [0x6][2] = { 0, UBO },
- [0x7][1] = { 0, UNKNOWN_2DWORDS },
- };
-
- *stage = lookup[state_block_id][state_type].stage;
- *state = lookup[state_block_id][state_type].state;
-}
-
-static void
-a4xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage, enum state_t *state,
- enum state_src_t *src)
-{
- unsigned state_block_id = (dwords[0] >> 18) & 0xf;
- unsigned state_type = dwords[1] & 0x3;
- _get_state_type(state_block_id, state_type, stage, state);
- *src = _get_state_src(dwords[0]);
-}
-
-static void
-a6xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage, enum state_t *state,
- enum state_src_t *src)
-{
- unsigned state_block_id = (dwords[0] >> 18) & 0xf;
- unsigned state_type = (dwords[0] >> 14) & 0x3;
- _get_state_type(state_block_id, state_type, stage, state);
- *src = _get_state_src(dwords[0]);
+ gl_shader_stage *stage, enum state_t *state)
+{
+ static const struct {
+ gl_shader_stage stage;
+ enum state_t state;
+ } lookup[0x10][0x4] = {
+ // SB4_VS_TEX:
+ [0x0][0] = {MESA_SHADER_VERTEX, TEX_SAMP},
+ [0x0][1] = {MESA_SHADER_VERTEX, TEX_CONST},
+ [0x0][2] = {MESA_SHADER_VERTEX, UBO},
+ // SB4_HS_TEX:
+ [0x1][0] = {MESA_SHADER_TESS_CTRL, TEX_SAMP},
+ [0x1][1] = {MESA_SHADER_TESS_CTRL, TEX_CONST},
+ [0x1][2] = {MESA_SHADER_TESS_CTRL, UBO},
+ // SB4_DS_TEX:
+ [0x2][0] = {MESA_SHADER_TESS_EVAL, TEX_SAMP},
+ [0x2][1] = {MESA_SHADER_TESS_EVAL, TEX_CONST},
+ [0x2][2] = {MESA_SHADER_TESS_EVAL, UBO},
+ // SB4_GS_TEX:
+ [0x3][0] = {MESA_SHADER_GEOMETRY, TEX_SAMP},
+ [0x3][1] = {MESA_SHADER_GEOMETRY, TEX_CONST},
+ [0x3][2] = {MESA_SHADER_GEOMETRY, UBO},
+ // SB4_FS_TEX:
+ [0x4][0] = {MESA_SHADER_FRAGMENT, TEX_SAMP},
+ [0x4][1] = {MESA_SHADER_FRAGMENT, TEX_CONST},
+ [0x4][2] = {MESA_SHADER_FRAGMENT, UBO},
+ // SB4_CS_TEX:
+ [0x5][0] = {MESA_SHADER_COMPUTE, TEX_SAMP},
+ [0x5][1] = {MESA_SHADER_COMPUTE, TEX_CONST},
+ [0x5][2] = {MESA_SHADER_COMPUTE, UBO},
+ // SB4_VS_SHADER:
+ [0x8][0] = {MESA_SHADER_VERTEX, SHADER_PROG},
+ [0x8][1] = {MESA_SHADER_VERTEX, SHADER_CONST},
+ [0x8][2] = {MESA_SHADER_VERTEX, UBO},
+ // SB4_HS_SHADER
+ [0x9][0] = {MESA_SHADER_TESS_CTRL, SHADER_PROG},
+ [0x9][1] = {MESA_SHADER_TESS_CTRL, SHADER_CONST},
+ [0x9][2] = {MESA_SHADER_TESS_CTRL, UBO},
+ // SB4_DS_SHADER
+ [0xa][0] = {MESA_SHADER_TESS_EVAL, SHADER_PROG},
+ [0xa][1] = {MESA_SHADER_TESS_EVAL, SHADER_CONST},
+ [0xa][2] = {MESA_SHADER_TESS_EVAL, UBO},
+ // SB4_GS_SHADER
+ [0xb][0] = {MESA_SHADER_GEOMETRY, SHADER_PROG},
+ [0xb][1] = {MESA_SHADER_GEOMETRY, SHADER_CONST},
+ [0xb][2] = {MESA_SHADER_GEOMETRY, UBO},
+ // SB4_FS_SHADER:
+ [0xc][0] = {MESA_SHADER_FRAGMENT, SHADER_PROG},
+ [0xc][1] = {MESA_SHADER_FRAGMENT, SHADER_CONST},
+ [0xc][2] = {MESA_SHADER_FRAGMENT, UBO},
+ // SB4_CS_SHADER:
+ [0xd][0] = {MESA_SHADER_COMPUTE, SHADER_PROG},
+ [0xd][1] = {MESA_SHADER_COMPUTE, SHADER_CONST},
+ [0xd][2] = {MESA_SHADER_COMPUTE, UBO},
+ [0xd][3] = {MESA_SHADER_COMPUTE, SSBO_0}, /* a6xx location */
+ // SB4_SSBO (shared across all stages)
+ [0xe][0] = {0, SSBO_0}, /* a5xx (and a4xx?) location */
+ [0xe][1] = {0, SSBO_1},
+ [0xe][2] = {0, SSBO_2},
+ // SB4_CS_SSBO
+ [0xf][0] = {MESA_SHADER_COMPUTE, SSBO_0},
+ [0xf][1] = {MESA_SHADER_COMPUTE, SSBO_1},
+ [0xf][2] = {MESA_SHADER_COMPUTE, SSBO_2},
+ // unknown things
+ /* This looks like combined UBO state for 3d stages (a5xx and
+ * before?? I think a6xx has UBO state per shader stage:
+ */
+ [0x6][2] = {0, UBO},
+ [0x7][1] = {0, UNKNOWN_2DWORDS},
+ };
+
+ *stage = lookup[state_block_id][state_type].stage;
+ *state = lookup[state_block_id][state_type].state;
+}
+
+static void
+a4xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage,
+ enum state_t *state, enum state_src_t *src)
+{
+ unsigned state_block_id = (dwords[0] >> 18) & 0xf;
+ unsigned state_type = dwords[1] & 0x3;
+ _get_state_type(state_block_id, state_type, stage, state);
+ *src = _get_state_src(dwords[0]);
+}
+
+static void
+a6xx_get_state_type(uint32_t *dwords, gl_shader_stage *stage,
+ enum state_t *state, enum state_src_t *src)
+{
+ unsigned state_block_id = (dwords[0] >> 18) & 0xf;
+ unsigned state_type = (dwords[0] >> 14) & 0x3;
+ _get_state_type(state_block_id, state_type, stage, state);
+ *src = _get_state_src(dwords[0]);
}
static void
dump_tex_samp(uint32_t *texsamp, enum state_src_t src, int num_unit, int level)
{
- for (int i = 0; i < num_unit; i++) {
- /* work-around to reduce noise for opencl blob which always
- * writes the max # regardless of # of textures used
- */
- if ((num_unit == 16) && (texsamp[0] == 0) && (texsamp[1] == 0))
- break;
-
- if ((300 <= options->gpu_id) && (options->gpu_id < 400)) {
- dump_domain(texsamp, 2, level+2, "A3XX_TEX_SAMP");
- dump_hex(texsamp, 2, level+1);
- texsamp += 2;
- } else if ((400 <= options->gpu_id) && (options->gpu_id < 500)) {
- dump_domain(texsamp, 2, level+2, "A4XX_TEX_SAMP");
- dump_hex(texsamp, 2, level+1);
- texsamp += 2;
- } else if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
- dump_domain(texsamp, 4, level+2, "A5XX_TEX_SAMP");
- dump_hex(texsamp, 4, level+1);
- texsamp += 4;
- } else if ((600 <= options->gpu_id) && (options->gpu_id < 700)) {
- dump_domain(texsamp, 4, level+2, "A6XX_TEX_SAMP");
- dump_hex(texsamp, 4, level+1);
- texsamp += src == STATE_SRC_BINDLESS ? 16 : 4;
- }
- }
+ for (int i = 0; i < num_unit; i++) {
+ /* work-around to reduce noise for opencl blob which always
+ * writes the max # regardless of # of textures used
+ */
+ if ((num_unit == 16) && (texsamp[0] == 0) && (texsamp[1] == 0))
+ break;
+
+ if ((300 <= options->gpu_id) && (options->gpu_id < 400)) {
+ dump_domain(texsamp, 2, level + 2, "A3XX_TEX_SAMP");
+ dump_hex(texsamp, 2, level + 1);
+ texsamp += 2;
+ } else if ((400 <= options->gpu_id) && (options->gpu_id < 500)) {
+ dump_domain(texsamp, 2, level + 2, "A4XX_TEX_SAMP");
+ dump_hex(texsamp, 2, level + 1);
+ texsamp += 2;
+ } else if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
+ dump_domain(texsamp, 4, level + 2, "A5XX_TEX_SAMP");
+ dump_hex(texsamp, 4, level + 1);
+ texsamp += 4;
+ } else if ((600 <= options->gpu_id) && (options->gpu_id < 700)) {
+ dump_domain(texsamp, 4, level + 2, "A6XX_TEX_SAMP");
+ dump_hex(texsamp, 4, level + 1);
+ texsamp += src == STATE_SRC_BINDLESS ? 16 : 4;
+ }
+ }
}
static void
dump_tex_const(uint32_t *texconst, int num_unit, int level)
{
- for (int i = 0; i < num_unit; i++) {
- /* work-around to reduce noise for opencl blob which always
- * writes the max # regardless of # of textures used
- */
- if ((num_unit == 16) &&
- (texconst[0] == 0) && (texconst[1] == 0) &&
- (texconst[2] == 0) && (texconst[3] == 0))
- break;
-
- if ((300 <= options->gpu_id) && (options->gpu_id < 400)) {
- dump_domain(texconst, 4, level+2, "A3XX_TEX_CONST");
- dump_hex(texconst, 4, level+1);
- texconst += 4;
- } else if ((400 <= options->gpu_id) && (options->gpu_id < 500)) {
- dump_domain(texconst, 8, level+2, "A4XX_TEX_CONST");
- if (options->dump_textures) {
- uint32_t addr = texconst[4] & ~0x1f;
- dump_gpuaddr(addr, level-2);
- }
- dump_hex(texconst, 8, level+1);
- texconst += 8;
- } else if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
- dump_domain(texconst, 12, level+2, "A5XX_TEX_CONST");
- if (options->dump_textures) {
- uint64_t addr = (((uint64_t)texconst[5] & 0x1ffff) << 32) | texconst[4];
- dump_gpuaddr_size(addr, level-2, hostlen(addr) / 4, 3);
- }
- dump_hex(texconst, 12, level+1);
- texconst += 12;
- } else if ((600 <= options->gpu_id) && (options->gpu_id < 700)) {
- dump_domain(texconst, 16, level+2, "A6XX_TEX_CONST");
- if (options->dump_textures) {
- uint64_t addr = (((uint64_t)texconst[5] & 0x1ffff) << 32) | texconst[4];
- dump_gpuaddr_size(addr, level-2, hostlen(addr) / 4, 3);
- }
- dump_hex(texconst, 16, level+1);
- texconst += 16;
- }
- }
+ for (int i = 0; i < num_unit; i++) {
+ /* work-around to reduce noise for opencl blob which always
+ * writes the max # regardless of # of textures used
+ */
+ if ((num_unit == 16) && (texconst[0] == 0) && (texconst[1] == 0) &&
+ (texconst[2] == 0) && (texconst[3] == 0))
+ break;
+
+ if ((300 <= options->gpu_id) && (options->gpu_id < 400)) {
+ dump_domain(texconst, 4, level + 2, "A3XX_TEX_CONST");
+ dump_hex(texconst, 4, level + 1);
+ texconst += 4;
+ } else if ((400 <= options->gpu_id) && (options->gpu_id < 500)) {
+ dump_domain(texconst, 8, level + 2, "A4XX_TEX_CONST");
+ if (options->dump_textures) {
+ uint32_t addr = texconst[4] & ~0x1f;
+ dump_gpuaddr(addr, level - 2);
+ }
+ dump_hex(texconst, 8, level + 1);
+ texconst += 8;
+ } else if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
+ dump_domain(texconst, 12, level + 2, "A5XX_TEX_CONST");
+ if (options->dump_textures) {
+ uint64_t addr =
+ (((uint64_t)texconst[5] & 0x1ffff) << 32) | texconst[4];
+ dump_gpuaddr_size(addr, level - 2, hostlen(addr) / 4, 3);
+ }
+ dump_hex(texconst, 12, level + 1);
+ texconst += 12;
+ } else if ((600 <= options->gpu_id) && (options->gpu_id < 700)) {
+ dump_domain(texconst, 16, level + 2, "A6XX_TEX_CONST");
+ if (options->dump_textures) {
+ uint64_t addr =
+ (((uint64_t)texconst[5] & 0x1ffff) << 32) | texconst[4];
+ dump_gpuaddr_size(addr, level - 2, hostlen(addr) / 4, 3);
+ }
+ dump_hex(texconst, 16, level + 1);
+ texconst += 16;
+ }
+ }
}
static void
cp_load_state(uint32_t *dwords, uint32_t sizedwords, int level)
{
- gl_shader_stage stage;
- enum state_t state;
- enum state_src_t src;
- uint32_t num_unit = (dwords[0] >> 22) & 0x1ff;
- uint64_t ext_src_addr;
- void *contents;
- int i;
-
- if (quiet(2) && !options->script)
- return;
-
- if (options->gpu_id >= 600)
- a6xx_get_state_type(dwords, &stage, &state, &src);
- else if (options->gpu_id >= 400)
- a4xx_get_state_type(dwords, &stage, &state, &src);
- else
- a3xx_get_state_type(dwords, &stage, &state, &src);
-
- switch (src) {
- case STATE_SRC_DIRECT: ext_src_addr = 0; break;
- case STATE_SRC_INDIRECT:
- if (is_64b()) {
- ext_src_addr = dwords[1] & 0xfffffffc;
- ext_src_addr |= ((uint64_t)dwords[2]) << 32;
- } else {
- ext_src_addr = dwords[1] & 0xfffffffc;
- }
-
- break;
- case STATE_SRC_BINDLESS: {
- const unsigned base_reg =
- stage == MESA_SHADER_COMPUTE ?
- regbase("HLSQ_CS_BINDLESS_BASE[0].ADDR") :
- regbase("HLSQ_BINDLESS_BASE[0].ADDR");
-
- if (is_64b()) {
- const unsigned reg = base_reg + (dwords[1] >> 28) * 2;
- ext_src_addr = reg_val(reg) & 0xfffffffc;
- ext_src_addr |= ((uint64_t)reg_val(reg + 1)) << 32;
- } else {
- const unsigned reg = base_reg + (dwords[1] >> 28);
- ext_src_addr = reg_val(reg) & 0xfffffffc;
- }
-
- ext_src_addr += 4 * (dwords[1] & 0xffffff);
- break;
- }
- }
-
- if (ext_src_addr)
- contents = hostptr(ext_src_addr);
- else
- contents = is_64b() ? dwords + 3 : dwords + 2;
-
- if (!contents)
- return;
-
- switch (state) {
- case SHADER_PROG: {
- const char *ext = NULL;
-
- if (quiet(2))
- return;
-
- if (options->gpu_id >= 400)
- num_unit *= 16;
- else if (options->gpu_id >= 300)
- num_unit *= 4;
-
- /* shaders:
- *
- * note: num_unit seems to be # of instruction groups, where
- * an instruction group has 4 64bit instructions.
- */
- if (stage == MESA_SHADER_VERTEX) {
- ext = "vo3";
- } else if (stage == MESA_SHADER_GEOMETRY) {
- ext = "go3";
- } else if (stage == MESA_SHADER_COMPUTE) {
- ext = "co3";
- } else if (stage == MESA_SHADER_FRAGMENT){
- ext = "fo3";
- }
-
- if (contents)
- try_disasm_a3xx(contents, num_unit * 2, level+2, stdout, options->gpu_id);
-
- /* dump raw shader: */
- if (ext)
- dump_shader(ext, contents, num_unit * 2 * 4);
-
- break;
- }
- case SHADER_CONST: {
- if (quiet(2))
- return;
-
- /* uniforms/consts:
- *
- * note: num_unit seems to be # of pairs of dwords??
- */
-
- if (options->gpu_id >= 400)
- num_unit *= 2;
-
- dump_float(contents, num_unit*2, level+1);
- dump_hex(contents, num_unit*2, level+1);
-
- break;
- }
- case TEX_MIPADDR: {
- uint32_t *addrs = contents;
-
- if (quiet(2))
- return;
-
- /* mipmap consts block just appears to be array of num_unit gpu addr's: */
- for (i = 0; i < num_unit; i++) {
- void *ptr = hostptr(addrs[i]);
- printf("%s%2d: %08x\n", levels[level+1], i, addrs[i]);
- if (options->dump_textures) {
- printf("base=%08x\n", (uint32_t)gpubaseaddr(addrs[i]));
- dump_hex(ptr, hostlen(addrs[i])/4, level+1);
- }
- }
- break;
- }
- case TEX_SAMP: {
- dump_tex_samp(contents, src, num_unit, level);
- break;
- }
- case TEX_CONST: {
- dump_tex_const(contents, num_unit, level);
- break;
- }
- case SSBO_0: {
- uint32_t *ssboconst = (uint32_t *)contents;
-
- for (i = 0; i < num_unit; i++) {
- int sz = 4;
- if (400 <= options->gpu_id && options->gpu_id < 500) {
- dump_domain(ssboconst, 4, level+2, "A4XX_SSBO_0");
- } else if (500 <= options->gpu_id && options->gpu_id < 600) {
- dump_domain(ssboconst, 4, level+2, "A5XX_SSBO_0");
- } else if (600 <= options->gpu_id && options->gpu_id < 700) {
- sz = 16;
- dump_domain(ssboconst, 16, level+2, "A6XX_IBO");
- }
- dump_hex(ssboconst, sz, level+1);
- ssboconst += sz;
- }
- break;
- }
- case SSBO_1: {
- uint32_t *ssboconst = (uint32_t *)contents;
-
- for (i = 0; i < num_unit; i++) {
- if (400 <= options->gpu_id && options->gpu_id < 500)
- dump_domain(ssboconst, 2, level+2, "A4XX_SSBO_1");
- else if (500 <= options->gpu_id && options->gpu_id < 600)
- dump_domain(ssboconst, 2, level+2, "A5XX_SSBO_1");
- dump_hex(ssboconst, 2, level+1);
- ssboconst += 2;
- }
- break;
- }
- case SSBO_2: {
- uint32_t *ssboconst = (uint32_t *)contents;
-
- for (i = 0; i < num_unit; i++) {
- /* TODO a4xx and a5xx might be same: */
- if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
- dump_domain(ssboconst, 2, level+2, "A5XX_SSBO_2");
- dump_hex(ssboconst, 2, level+1);
- }
- if (options->dump_textures) {
- uint64_t addr = (((uint64_t)ssboconst[1] & 0x1ffff) << 32) | ssboconst[0];
- dump_gpuaddr_size(addr, level-2, hostlen(addr) / 4, 3);
- }
- ssboconst += 2;
- }
- break;
- }
- case UBO: {
- uint32_t *uboconst = (uint32_t *)contents;
-
- for (i = 0; i < num_unit; i++) {
- // TODO probably similar on a4xx..
- if (500 <= options->gpu_id && options->gpu_id < 600)
- dump_domain(uboconst, 2, level+2, "A5XX_UBO");
- else if (600 <= options->gpu_id && options->gpu_id < 700)
- dump_domain(uboconst, 2, level+2, "A6XX_UBO");
- dump_hex(uboconst, 2, level+1);
- uboconst += src == STATE_SRC_BINDLESS ? 16 : 2;
- }
- break;
- }
- case UNKNOWN_DWORDS: {
- if (quiet(2))
- return;
- dump_hex(contents, num_unit, level+1);
- break;
- }
- case UNKNOWN_2DWORDS: {
- if (quiet(2))
- return;
- dump_hex(contents, num_unit * 2, level+1);
- break;
- }
- case UNKNOWN_4DWORDS: {
- if (quiet(2))
- return;
- dump_hex(contents, num_unit * 4, level+1);
- break;
- }
- default:
- if (quiet(2))
- return;
- /* hmm.. */
- dump_hex(contents, num_unit, level+1);
- break;
- }
+ gl_shader_stage stage;
+ enum state_t state;
+ enum state_src_t src;
+ uint32_t num_unit = (dwords[0] >> 22) & 0x1ff;
+ uint64_t ext_src_addr;
+ void *contents;
+ int i;
+
+ if (quiet(2) && !options->script)
+ return;
+
+ if (options->gpu_id >= 600)
+ a6xx_get_state_type(dwords, &stage, &state, &src);
+ else if (options->gpu_id >= 400)
+ a4xx_get_state_type(dwords, &stage, &state, &src);
+ else
+ a3xx_get_state_type(dwords, &stage, &state, &src);
+
+ switch (src) {
+ case STATE_SRC_DIRECT:
+ ext_src_addr = 0;
+ break;
+ case STATE_SRC_INDIRECT:
+ if (is_64b()) {
+ ext_src_addr = dwords[1] & 0xfffffffc;
+ ext_src_addr |= ((uint64_t)dwords[2]) << 32;
+ } else {
+ ext_src_addr = dwords[1] & 0xfffffffc;
+ }
+
+ break;
+ case STATE_SRC_BINDLESS: {
+ const unsigned base_reg = stage == MESA_SHADER_COMPUTE
+ ? regbase("HLSQ_CS_BINDLESS_BASE[0].ADDR")
+ : regbase("HLSQ_BINDLESS_BASE[0].ADDR");
+
+ if (is_64b()) {
+ const unsigned reg = base_reg + (dwords[1] >> 28) * 2;
+ ext_src_addr = reg_val(reg) & 0xfffffffc;
+ ext_src_addr |= ((uint64_t)reg_val(reg + 1)) << 32;
+ } else {
+ const unsigned reg = base_reg + (dwords[1] >> 28);
+ ext_src_addr = reg_val(reg) & 0xfffffffc;
+ }
+
+ ext_src_addr += 4 * (dwords[1] & 0xffffff);
+ break;
+ }
+ }
+
+ if (ext_src_addr)
+ contents = hostptr(ext_src_addr);
+ else
+ contents = is_64b() ? dwords + 3 : dwords + 2;
+
+ if (!contents)
+ return;
+
+ switch (state) {
+ case SHADER_PROG: {
+ const char *ext = NULL;
+
+ if (quiet(2))
+ return;
+
+ if (options->gpu_id >= 400)
+ num_unit *= 16;
+ else if (options->gpu_id >= 300)
+ num_unit *= 4;
+
+ /* shaders:
+ *
+ * note: num_unit seems to be # of instruction groups, where
+ * an instruction group has 4 64bit instructions.
+ */
+ if (stage == MESA_SHADER_VERTEX) {
+ ext = "vo3";
+ } else if (stage == MESA_SHADER_GEOMETRY) {
+ ext = "go3";
+ } else if (stage == MESA_SHADER_COMPUTE) {
+ ext = "co3";
+ } else if (stage == MESA_SHADER_FRAGMENT) {
+ ext = "fo3";
+ }
+
+ if (contents)
+ try_disasm_a3xx(contents, num_unit * 2, level + 2, stdout,
+ options->gpu_id);
+
+ /* dump raw shader: */
+ if (ext)
+ dump_shader(ext, contents, num_unit * 2 * 4);
+
+ break;
+ }
+ case SHADER_CONST: {
+ if (quiet(2))
+ return;
+
+ /* uniforms/consts:
+ *
+ * note: num_unit seems to be # of pairs of dwords??
+ */
+
+ if (options->gpu_id >= 400)
+ num_unit *= 2;
+
+ dump_float(contents, num_unit * 2, level + 1);
+ dump_hex(contents, num_unit * 2, level + 1);
+
+ break;
+ }
+ case TEX_MIPADDR: {
+ uint32_t *addrs = contents;
+
+ if (quiet(2))
+ return;
+
+ /* mipmap consts block just appears to be array of num_unit gpu addr's: */
+ for (i = 0; i < num_unit; i++) {
+ void *ptr = hostptr(addrs[i]);
+ printf("%s%2d: %08x\n", levels[level + 1], i, addrs[i]);
+ if (options->dump_textures) {
+ printf("base=%08x\n", (uint32_t)gpubaseaddr(addrs[i]));
+ dump_hex(ptr, hostlen(addrs[i]) / 4, level + 1);
+ }
+ }
+ break;
+ }
+ case TEX_SAMP: {
+ dump_tex_samp(contents, src, num_unit, level);
+ break;
+ }
+ case TEX_CONST: {
+ dump_tex_const(contents, num_unit, level);
+ break;
+ }
+ case SSBO_0: {
+ uint32_t *ssboconst = (uint32_t *)contents;
+
+ for (i = 0; i < num_unit; i++) {
+ int sz = 4;
+ if (400 <= options->gpu_id && options->gpu_id < 500) {
+ dump_domain(ssboconst, 4, level + 2, "A4XX_SSBO_0");
+ } else if (500 <= options->gpu_id && options->gpu_id < 600) {
+ dump_domain(ssboconst, 4, level + 2, "A5XX_SSBO_0");
+ } else if (600 <= options->gpu_id && options->gpu_id < 700) {
+ sz = 16;
+ dump_domain(ssboconst, 16, level + 2, "A6XX_IBO");
+ }
+ dump_hex(ssboconst, sz, level + 1);
+ ssboconst += sz;
+ }
+ break;
+ }
+ case SSBO_1: {
+ uint32_t *ssboconst = (uint32_t *)contents;
+
+ for (i = 0; i < num_unit; i++) {
+ if (400 <= options->gpu_id && options->gpu_id < 500)
+ dump_domain(ssboconst, 2, level + 2, "A4XX_SSBO_1");
+ else if (500 <= options->gpu_id && options->gpu_id < 600)
+ dump_domain(ssboconst, 2, level + 2, "A5XX_SSBO_1");
+ dump_hex(ssboconst, 2, level + 1);
+ ssboconst += 2;
+ }
+ break;
+ }
+ case SSBO_2: {
+ uint32_t *ssboconst = (uint32_t *)contents;
+
+ for (i = 0; i < num_unit; i++) {
+ /* TODO a4xx and a5xx might be same: */
+ if ((500 <= options->gpu_id) && (options->gpu_id < 600)) {
+ dump_domain(ssboconst, 2, level + 2, "A5XX_SSBO_2");
+ dump_hex(ssboconst, 2, level + 1);
+ }
+ if (options->dump_textures) {
+ uint64_t addr =
+ (((uint64_t)ssboconst[1] & 0x1ffff) << 32) | ssboconst[0];
+ dump_gpuaddr_size(addr, level - 2, hostlen(addr) / 4, 3);
+ }
+ ssboconst += 2;
+ }
+ break;
+ }
+ case UBO: {
+ uint32_t *uboconst = (uint32_t *)contents;
+
+ for (i = 0; i < num_unit; i++) {
+ // TODO probably similar on a4xx..
+ if (500 <= options->gpu_id && options->gpu_id < 600)
+ dump_domain(uboconst, 2, level + 2, "A5XX_UBO");
+ else if (600 <= options->gpu_id && options->gpu_id < 700)
+ dump_domain(uboconst, 2, level + 2, "A6XX_UBO");
+ dump_hex(uboconst, 2, level + 1);
+ uboconst += src == STATE_SRC_BINDLESS ? 16 : 2;
+ }
+ break;
+ }
+ case UNKNOWN_DWORDS: {
+ if (quiet(2))
+ return;
+ dump_hex(contents, num_unit, level + 1);
+ break;
+ }
+ case UNKNOWN_2DWORDS: {
+ if (quiet(2))
+ return;
+ dump_hex(contents, num_unit * 2, level + 1);
+ break;
+ }
+ case UNKNOWN_4DWORDS: {
+ if (quiet(2))
+ return;
+ dump_hex(contents, num_unit * 4, level + 1);
+ break;
+ }
+ default:
+ if (quiet(2))
+ return;
+ /* hmm.. */
+ dump_hex(contents, num_unit, level + 1);
+ break;
+ }
}
static void
cp_set_bin(uint32_t *dwords, uint32_t sizedwords, int level)
{
- bin_x1 = dwords[1] & 0xffff;
- bin_y1 = dwords[1] >> 16;
- bin_x2 = dwords[2] & 0xffff;
- bin_y2 = dwords[2] >> 16;
-}
-
-static void
-dump_a2xx_tex_const(uint32_t *dwords, uint32_t sizedwords, uint32_t val, int level)
-{
- uint32_t w, h, p;
- uint32_t gpuaddr, flags, mip_gpuaddr, mip_flags;
- uint32_t min, mag, swiz, clamp_x, clamp_y, clamp_z;
- static const char *filter[] = {
- "point", "bilinear", "bicubic",
- };
- static const char *clamp[] = {
- "wrap", "mirror", "clamp-last-texel",
- };
- static const char swiznames[] = "xyzw01??";
-
- /* see sys2gmem_tex_const[] in adreno_a2xxx.c */
-
- /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
- * RFMode=ZeroClamp-1, Dim=1:2d, pitch
- */
- p = (dwords[0] >> 22) << 5;
- clamp_x = (dwords[0] >> 10) & 0x3;
- clamp_y = (dwords[0] >> 13) & 0x3;
- clamp_z = (dwords[0] >> 16) & 0x3;
-
- /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
- * NearestClamp=1:OGL Mode
- */
- parse_dword_addr(dwords[1], &gpuaddr, &flags, 0xfff);
-
- /* Width, Height, EndianSwap=0:None */
- w = (dwords[2] & 0x1fff) + 1;
- h = ((dwords[2] >> 13) & 0x1fff) + 1;
-
- /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
- * Mip=2:BaseMap
- */
- mag = (dwords[3] >> 19) & 0x3;
- min = (dwords[3] >> 21) & 0x3;
- swiz = (dwords[3] >> 1) & 0xfff;
-
- /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
- * Dim3d=0
- */
- // XXX
-
- /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
- * Dim=1:2d, MipPacking=0
- */
- parse_dword_addr(dwords[5], &mip_gpuaddr, &mip_flags, 0xfff);
-
- printf("%sset texture const %04x\n", levels[level], val);
- printf("%sclamp x/y/z: %s/%s/%s\n", levels[level+1],
- clamp[clamp_x], clamp[clamp_y], clamp[clamp_z]);
- printf("%sfilter min/mag: %s/%s\n", levels[level+1], filter[min], filter[mag]);
- printf("%sswizzle: %c%c%c%c\n", levels[level+1],
- swiznames[(swiz >> 0) & 0x7], swiznames[(swiz >> 3) & 0x7],
- swiznames[(swiz >> 6) & 0x7], swiznames[(swiz >> 9) & 0x7]);
- printf("%saddr=%08x (flags=%03x), size=%dx%d, pitch=%d, format=%s\n",
- levels[level+1], gpuaddr, flags, w, h, p,
- rnn_enumname(rnn, "a2xx_sq_surfaceformat", flags & 0xf));
- printf("%smipaddr=%08x (flags=%03x)\n", levels[level+1],
- mip_gpuaddr, mip_flags);
-}
-
-static void
-dump_a2xx_shader_const(uint32_t *dwords, uint32_t sizedwords, uint32_t val, int level)
-{
- int i;
- printf("%sset shader const %04x\n", levels[level], val);
- for (i = 0; i < sizedwords; ) {
- uint32_t gpuaddr, flags;
- parse_dword_addr(dwords[i++], &gpuaddr, &flags, 0xf);
- void *addr = hostptr(gpuaddr);
- if (addr) {
- const char * fmt =
- rnn_enumname(rnn, "a2xx_sq_surfaceformat", flags & 0xf);
- uint32_t size = dwords[i++];
- printf("%saddr=%08x, size=%d, format=%s\n", levels[level+1],
- gpuaddr, size, fmt);
- // TODO maybe dump these as bytes instead of dwords?
- size = (size + 3) / 4; // for now convert to dwords
- dump_hex(addr, min(size, 64), level + 1);
- if (size > min(size, 64))
- printf("%s\t\t...\n", levels[level+1]);
- dump_float(addr, min(size, 64), level + 1);
- if (size > min(size, 64))
- printf("%s\t\t...\n", levels[level+1]);
- }
- }
+ bin_x1 = dwords[1] & 0xffff;
+ bin_y1 = dwords[1] >> 16;
+ bin_x2 = dwords[2] & 0xffff;
+ bin_y2 = dwords[2] >> 16;
+}
+
+static void
+dump_a2xx_tex_const(uint32_t *dwords, uint32_t sizedwords, uint32_t val,
+ int level)
+{
+ uint32_t w, h, p;
+ uint32_t gpuaddr, flags, mip_gpuaddr, mip_flags;
+ uint32_t min, mag, swiz, clamp_x, clamp_y, clamp_z;
+ static const char *filter[] = {
+ "point",
+ "bilinear",
+ "bicubic",
+ };
+ static const char *clamp[] = {
+ "wrap",
+ "mirror",
+ "clamp-last-texel",
+ };
+ static const char swiznames[] = "xyzw01??";
+
+ /* see sys2gmem_tex_const[] in adreno_a2xxx.c */
+
+ /* Texture, FormatXYZW=Unsigned, ClampXYZ=Wrap/Repeat,
+ * RFMode=ZeroClamp-1, Dim=1:2d, pitch
+ */
+ p = (dwords[0] >> 22) << 5;
+ clamp_x = (dwords[0] >> 10) & 0x3;
+ clamp_y = (dwords[0] >> 13) & 0x3;
+ clamp_z = (dwords[0] >> 16) & 0x3;
+
+ /* Format=6:8888_WZYX, EndianSwap=0:None, ReqSize=0:256bit, DimHi=0,
+ * NearestClamp=1:OGL Mode
+ */
+ parse_dword_addr(dwords[1], &gpuaddr, &flags, 0xfff);
+
+ /* Width, Height, EndianSwap=0:None */
+ w = (dwords[2] & 0x1fff) + 1;
+ h = ((dwords[2] >> 13) & 0x1fff) + 1;
+
+ /* NumFormat=0:RF, DstSelXYZW=XYZW, ExpAdj=0, MagFilt=MinFilt=0:Point,
+ * Mip=2:BaseMap
+ */
+ mag = (dwords[3] >> 19) & 0x3;
+ min = (dwords[3] >> 21) & 0x3;
+ swiz = (dwords[3] >> 1) & 0xfff;
+
+ /* VolMag=VolMin=0:Point, MinMipLvl=0, MaxMipLvl=1, LodBiasH=V=0,
+ * Dim3d=0
+ */
+ // XXX
+
+ /* BorderColor=0:ABGRBlack, ForceBC=0:diable, TriJuice=0, Aniso=0,
+ * Dim=1:2d, MipPacking=0
+ */
+ parse_dword_addr(dwords[5], &mip_gpuaddr, &mip_flags, 0xfff);
+
+ printf("%sset texture const %04x\n", levels[level], val);
+ printf("%sclamp x/y/z: %s/%s/%s\n", levels[level + 1], clamp[clamp_x],
+ clamp[clamp_y], clamp[clamp_z]);
+ printf("%sfilter min/mag: %s/%s\n", levels[level + 1], filter[min],
+ filter[mag]);
+ printf("%sswizzle: %c%c%c%c\n", levels[level + 1],
+ swiznames[(swiz >> 0) & 0x7], swiznames[(swiz >> 3) & 0x7],
+ swiznames[(swiz >> 6) & 0x7], swiznames[(swiz >> 9) & 0x7]);
+ printf("%saddr=%08x (flags=%03x), size=%dx%d, pitch=%d, format=%s\n",
+ levels[level + 1], gpuaddr, flags, w, h, p,
+ rnn_enumname(rnn, "a2xx_sq_surfaceformat", flags & 0xf));
+ printf("%smipaddr=%08x (flags=%03x)\n", levels[level + 1], mip_gpuaddr,
+ mip_flags);
+}
+
+static void
+dump_a2xx_shader_const(uint32_t *dwords, uint32_t sizedwords, uint32_t val,
+ int level)
+{
+ int i;
+ printf("%sset shader const %04x\n", levels[level], val);
+ for (i = 0; i < sizedwords;) {
+ uint32_t gpuaddr, flags;
+ parse_dword_addr(dwords[i++], &gpuaddr, &flags, 0xf);
+ void *addr = hostptr(gpuaddr);
+ if (addr) {
+ const char *fmt =
+ rnn_enumname(rnn, "a2xx_sq_surfaceformat", flags & 0xf);
+ uint32_t size = dwords[i++];
+ printf("%saddr=%08x, size=%d, format=%s\n", levels[level + 1], gpuaddr,
+ size, fmt);
+ // TODO maybe dump these as bytes instead of dwords?
+ size = (size + 3) / 4; // for now convert to dwords
+ dump_hex(addr, min(size, 64), level + 1);
+ if (size > min(size, 64))
+ printf("%s\t\t...\n", levels[level + 1]);
+ dump_float(addr, min(size, 64), level + 1);
+ if (size > min(size, 64))
+ printf("%s\t\t...\n", levels[level + 1]);
+ }
+ }
}
static void
cp_set_const(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t val = dwords[0] & 0xffff;
- switch((dwords[0] >> 16) & 0xf) {
- case 0x0:
- dump_float((float *)(dwords+1), sizedwords-1, level+1);
- break;
- case 0x1:
- /* need to figure out how const space is partitioned between
- * attributes, textures, etc..
- */
- if (val < 0x78) {
- dump_a2xx_tex_const(dwords+1, sizedwords-1, val, level);
- } else {
- dump_a2xx_shader_const(dwords+1, sizedwords-1, val, level);
- }
- break;
- case 0x2:
- printf("%sset bool const %04x\n", levels[level], val);
- break;
- case 0x3:
- printf("%sset loop const %04x\n", levels[level], val);
- break;
- case 0x4:
- val += 0x2000;
- if (dwords[0] & 0x80000000) {
- uint32_t srcreg = dwords[1];
- uint32_t dstval = dwords[2];
-
- /* TODO: not sure what happens w/ payload != 2.. */
- assert(sizedwords == 3);
- assert(srcreg < ARRAY_SIZE(type0_reg_vals));
-
- /* note: rnn_regname uses a static buf so we can't do
- * two regname() calls for one printf..
- */
- printf("%s%s = %08x + ", levels[level], regname(val, 1), dstval);
- printf("%s (%08x)\n", regname(srcreg, 1), type0_reg_vals[srcreg]);
-
- dstval += type0_reg_vals[srcreg];
-
- dump_registers(val, &dstval, 1, level+1);
- } else {
- dump_registers(val, dwords+1, sizedwords-1, level+1);
- }
- break;
- }
+ uint32_t val = dwords[0] & 0xffff;
+ switch ((dwords[0] >> 16) & 0xf) {
+ case 0x0:
+ dump_float((float *)(dwords + 1), sizedwords - 1, level + 1);
+ break;
+ case 0x1:
+ /* need to figure out how const space is partitioned between
+ * attributes, textures, etc..
+ */
+ if (val < 0x78) {
+ dump_a2xx_tex_const(dwords + 1, sizedwords - 1, val, level);
+ } else {
+ dump_a2xx_shader_const(dwords + 1, sizedwords - 1, val, level);
+ }
+ break;
+ case 0x2:
+ printf("%sset bool const %04x\n", levels[level], val);
+ break;
+ case 0x3:
+ printf("%sset loop const %04x\n", levels[level], val);
+ break;
+ case 0x4:
+ val += 0x2000;
+ if (dwords[0] & 0x80000000) {
+ uint32_t srcreg = dwords[1];
+ uint32_t dstval = dwords[2];
+
+ /* TODO: not sure what happens w/ payload != 2.. */
+ assert(sizedwords == 3);
+ assert(srcreg < ARRAY_SIZE(type0_reg_vals));
+
+ /* note: rnn_regname uses a static buf so we can't do
+ * two regname() calls for one printf..
+ */
+ printf("%s%s = %08x + ", levels[level], regname(val, 1), dstval);
+ printf("%s (%08x)\n", regname(srcreg, 1), type0_reg_vals[srcreg]);
+
+ dstval += type0_reg_vals[srcreg];
+
+ dump_registers(val, &dstval, 1, level + 1);
+ } else {
+ dump_registers(val, dwords + 1, sizedwords - 1, level + 1);
+ }
+ break;
+ }
}
static void dump_register_summary(int level);
@@ -1795,445 +1812,447 @@ static void dump_register_summary(int level);
static void
cp_event_write(uint32_t *dwords, uint32_t sizedwords, int level)
{
- const char *name = rnn_enumname(rnn, "vgt_event_type", dwords[0]);
- printl(2, "%sevent %s\n", levels[level], name);
+ const char *name = rnn_enumname(rnn, "vgt_event_type", dwords[0]);
+ printl(2, "%sevent %s\n", levels[level], name);
- if (name && (options->gpu_id > 500)) {
- char eventname[64];
- snprintf(eventname, sizeof(eventname), "EVENT:%s", name);
- if (!strcmp(name, "BLIT")) {
- do_query(eventname, 0);
- print_mode(level);
- dump_register_summary(level);
- }
- }
+ if (name && (options->gpu_id > 500)) {
+ char eventname[64];
+ snprintf(eventname, sizeof(eventname), "EVENT:%s", name);
+ if (!strcmp(name, "BLIT")) {
+ do_query(eventname, 0);
+ print_mode(level);
+ dump_register_summary(level);
+ }
+ }
}
static void
dump_register_summary(int level)
{
- uint32_t i;
- bool saved_summary = summary;
- summary = false;
-
- in_summary = true;
-
- /* dump current state of registers: */
- printl(2, "%sdraw[%i] register values\n", levels[level], draw_count);
- for (i = 0; i < regcnt(); i++) {
- uint32_t regbase = i;
- uint32_t lastval = reg_val(regbase);
- /* skip registers that haven't been updated since last draw/blit: */
- if (!(options->allregs || reg_rewritten(regbase)))
- continue;
- if (!reg_written(regbase))
- continue;
- if (lastval != lastvals[regbase]) {
- printl(2, "!");
- lastvals[regbase] = lastval;
- } else {
- printl(2, " ");
- }
- if (reg_rewritten(regbase)) {
- printl(2, "+");
- } else {
- printl(2, " ");
- }
- printl(2, "\t%08x", lastval);
- if (!quiet(2)) {
- dump_register(regbase, lastval, level);
- }
- }
-
- clear_rewritten();
-
- in_summary = false;
-
- draw_count++;
- summary = saved_summary;
+ uint32_t i;
+ bool saved_summary = summary;
+ summary = false;
+
+ in_summary = true;
+
+ /* dump current state of registers: */
+ printl(2, "%sdraw[%i] register values\n", levels[level], draw_count);
+ for (i = 0; i < regcnt(); i++) {
+ uint32_t regbase = i;
+ uint32_t lastval = reg_val(regbase);
+ /* skip registers that haven't been updated since last draw/blit: */
+ if (!(options->allregs || reg_rewritten(regbase)))
+ continue;
+ if (!reg_written(regbase))
+ continue;
+ if (lastval != lastvals[regbase]) {
+ printl(2, "!");
+ lastvals[regbase] = lastval;
+ } else {
+ printl(2, " ");
+ }
+ if (reg_rewritten(regbase)) {
+ printl(2, "+");
+ } else {
+ printl(2, " ");
+ }
+ printl(2, "\t%08x", lastval);
+ if (!quiet(2)) {
+ dump_register(regbase, lastval, level);
+ }
+ }
+
+ clear_rewritten();
+
+ in_summary = false;
+
+ draw_count++;
+ summary = saved_summary;
}
static uint32_t
draw_indx_common(uint32_t *dwords, int level)
{
- uint32_t prim_type = dwords[1] & 0x1f;
- uint32_t source_select = (dwords[1] >> 6) & 0x3;
- uint32_t num_indices = dwords[2];
- const char *primtype;
+ uint32_t prim_type = dwords[1] & 0x1f;
+ uint32_t source_select = (dwords[1] >> 6) & 0x3;
+ uint32_t num_indices = dwords[2];
+ const char *primtype;
- primtype = rnn_enumname(rnn, "pc_di_primtype", prim_type);
+ primtype = rnn_enumname(rnn, "pc_di_primtype", prim_type);
- do_query(primtype, num_indices);
+ do_query(primtype, num_indices);
- printl(2, "%sdraw: %d\n", levels[level], draws[ib]);
- printl(2, "%sprim_type: %s (%d)\n", levels[level], primtype,
- prim_type);
- printl(2, "%ssource_select: %s (%d)\n", levels[level],
- rnn_enumname(rnn, "pc_di_src_sel", source_select),
- source_select);
- printl(2, "%snum_indices: %d\n", levels[level], num_indices);
+ printl(2, "%sdraw: %d\n", levels[level], draws[ib]);
+ printl(2, "%sprim_type: %s (%d)\n", levels[level], primtype, prim_type);
+ printl(2, "%ssource_select: %s (%d)\n", levels[level],
+ rnn_enumname(rnn, "pc_di_src_sel", source_select), source_select);
+ printl(2, "%snum_indices: %d\n", levels[level], num_indices);
- vertices += num_indices;
+ vertices += num_indices;
- draws[ib]++;
+ draws[ib]++;
- return num_indices;
+ return num_indices;
}
enum pc_di_index_size {
- INDEX_SIZE_IGN = 0,
- INDEX_SIZE_16_BIT = 0,
- INDEX_SIZE_32_BIT = 1,
- INDEX_SIZE_8_BIT = 2,
- INDEX_SIZE_INVALID = 0,
+ INDEX_SIZE_IGN = 0,
+ INDEX_SIZE_16_BIT = 0,
+ INDEX_SIZE_32_BIT = 1,
+ INDEX_SIZE_8_BIT = 2,
+ INDEX_SIZE_INVALID = 0,
};
static void
cp_draw_indx(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t num_indices = draw_indx_common(dwords, level);
-
- assert(!is_64b());
-
- /* if we have an index buffer, dump that: */
- if (sizedwords == 5) {
- void *ptr = hostptr(dwords[3]);
- printl(2, "%sgpuaddr: %08x\n", levels[level], dwords[3]);
- printl(2, "%sidx_size: %d\n", levels[level], dwords[4]);
- if (ptr) {
- enum pc_di_index_size size =
- ((dwords[1] >> 11) & 1) | ((dwords[1] >> 12) & 2);
- if (!quiet(2)) {
- int i;
- printf("%sidxs: ", levels[level]);
- if (size == INDEX_SIZE_8_BIT) {
- uint8_t *idx = ptr;
- for (i = 0; i < dwords[4]; i++)
- printf(" %u", idx[i]);
- } else if (size == INDEX_SIZE_16_BIT) {
- uint16_t *idx = ptr;
- for (i = 0; i < dwords[4]/2; i++)
- printf(" %u", idx[i]);
- } else if (size == INDEX_SIZE_32_BIT) {
- uint32_t *idx = ptr;
- for (i = 0; i < dwords[4]/4; i++)
- printf(" %u", idx[i]);
- }
- printf("\n");
- dump_hex(ptr, dwords[4]/4, level+1);
- }
- }
- }
-
- /* don't bother dumping registers for the dummy draw_indx's.. */
- if (num_indices > 0)
- dump_register_summary(level);
-
- needs_wfi = true;
+ uint32_t num_indices = draw_indx_common(dwords, level);
+
+ assert(!is_64b());
+
+ /* if we have an index buffer, dump that: */
+ if (sizedwords == 5) {
+ void *ptr = hostptr(dwords[3]);
+ printl(2, "%sgpuaddr: %08x\n", levels[level], dwords[3]);
+ printl(2, "%sidx_size: %d\n", levels[level], dwords[4]);
+ if (ptr) {
+ enum pc_di_index_size size =
+ ((dwords[1] >> 11) & 1) | ((dwords[1] >> 12) & 2);
+ if (!quiet(2)) {
+ int i;
+ printf("%sidxs: ", levels[level]);
+ if (size == INDEX_SIZE_8_BIT) {
+ uint8_t *idx = ptr;
+ for (i = 0; i < dwords[4]; i++)
+ printf(" %u", idx[i]);
+ } else if (size == INDEX_SIZE_16_BIT) {
+ uint16_t *idx = ptr;
+ for (i = 0; i < dwords[4] / 2; i++)
+ printf(" %u", idx[i]);
+ } else if (size == INDEX_SIZE_32_BIT) {
+ uint32_t *idx = ptr;
+ for (i = 0; i < dwords[4] / 4; i++)
+ printf(" %u", idx[i]);
+ }
+ printf("\n");
+ dump_hex(ptr, dwords[4] / 4, level + 1);
+ }
+ }
+ }
+
+ /* don't bother dumping registers for the dummy draw_indx's.. */
+ if (num_indices > 0)
+ dump_register_summary(level);
+
+ needs_wfi = true;
}
static void
cp_draw_indx_2(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t num_indices = draw_indx_common(dwords, level);
- enum pc_di_index_size size =
- ((dwords[1] >> 11) & 1) | ((dwords[1] >> 12) & 2);
- void *ptr = &dwords[3];
- int sz = 0;
-
- assert(!is_64b());
-
- /* CP_DRAW_INDX_2 has embedded/inline idx buffer: */
- if (!quiet(2)) {
- int i;
- printf("%sidxs: ", levels[level]);
- if (size == INDEX_SIZE_8_BIT) {
- uint8_t *idx = ptr;
- for (i = 0; i < num_indices; i++)
- printf(" %u", idx[i]);
- sz = num_indices;
- } else if (size == INDEX_SIZE_16_BIT) {
- uint16_t *idx = ptr;
- for (i = 0; i < num_indices; i++)
- printf(" %u", idx[i]);
- sz = num_indices * 2;
- } else if (size == INDEX_SIZE_32_BIT) {
- uint32_t *idx = ptr;
- for (i = 0; i < num_indices; i++)
- printf(" %u", idx[i]);
- sz = num_indices * 4;
- }
- printf("\n");
- dump_hex(ptr, sz / 4, level+1);
- }
-
- /* don't bother dumping registers for the dummy draw_indx's.. */
- if (num_indices > 0)
- dump_register_summary(level);
+ uint32_t num_indices = draw_indx_common(dwords, level);
+ enum pc_di_index_size size =
+ ((dwords[1] >> 11) & 1) | ((dwords[1] >> 12) & 2);
+ void *ptr = &dwords[3];
+ int sz = 0;
+
+ assert(!is_64b());
+
+ /* CP_DRAW_INDX_2 has embedded/inline idx buffer: */
+ if (!quiet(2)) {
+ int i;
+ printf("%sidxs: ", levels[level]);
+ if (size == INDEX_SIZE_8_BIT) {
+ uint8_t *idx = ptr;
+ for (i = 0; i < num_indices; i++)
+ printf(" %u", idx[i]);
+ sz = num_indices;
+ } else if (size == INDEX_SIZE_16_BIT) {
+ uint16_t *idx = ptr;
+ for (i = 0; i < num_indices; i++)
+ printf(" %u", idx[i]);
+ sz = num_indices * 2;
+ } else if (size == INDEX_SIZE_32_BIT) {
+ uint32_t *idx = ptr;
+ for (i = 0; i < num_indices; i++)
+ printf(" %u", idx[i]);
+ sz = num_indices * 4;
+ }
+ printf("\n");
+ dump_hex(ptr, sz / 4, level + 1);
+ }
+
+ /* don't bother dumping registers for the dummy draw_indx's.. */
+ if (num_indices > 0)
+ dump_register_summary(level);
}
static void
cp_draw_indx_offset(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t num_indices = dwords[2];
- uint32_t prim_type = dwords[0] & 0x1f;
+ uint32_t num_indices = dwords[2];
+ uint32_t prim_type = dwords[0] & 0x1f;
- do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), num_indices);
- print_mode(level);
+ do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), num_indices);
+ print_mode(level);
- /* don't bother dumping registers for the dummy draw_indx's.. */
- if (num_indices > 0)
- dump_register_summary(level);
+ /* don't bother dumping registers for the dummy draw_indx's.. */
+ if (num_indices > 0)
+ dump_register_summary(level);
}
static void
cp_draw_indx_indirect(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t prim_type = dwords[0] & 0x1f;
- uint64_t addr;
+ uint32_t prim_type = dwords[0] & 0x1f;
+ uint64_t addr;
- do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
- print_mode(level);
+ do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
+ print_mode(level);
- if (is_64b())
- addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
- else
- addr = dwords[1];
- dump_gpuaddr_size(addr, level, 0x10, 2);
+ if (is_64b())
+ addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
+ else
+ addr = dwords[1];
+ dump_gpuaddr_size(addr, level, 0x10, 2);
- if (is_64b())
- addr = (((uint64_t)dwords[5] & 0x1ffff) << 32) | dwords[4];
- else
- addr = dwords[3];
- dump_gpuaddr_size(addr, level, 0x10, 2);
+ if (is_64b())
+ addr = (((uint64_t)dwords[5] & 0x1ffff) << 32) | dwords[4];
+ else
+ addr = dwords[3];
+ dump_gpuaddr_size(addr, level, 0x10, 2);
- dump_register_summary(level);
+ dump_register_summary(level);
}
static void
cp_draw_indirect(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t prim_type = dwords[0] & 0x1f;
- uint64_t addr;
+ uint32_t prim_type = dwords[0] & 0x1f;
+ uint64_t addr;
- do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
- print_mode(level);
+ do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
+ print_mode(level);
- addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
- dump_gpuaddr_size(addr, level, 0x10, 2);
+ addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
+ dump_gpuaddr_size(addr, level, 0x10, 2);
- dump_register_summary(level);
+ dump_register_summary(level);
}
static void
cp_draw_indirect_multi(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t prim_type = dwords[0] & 0x1f;
- uint32_t count = dwords[2];
-
- do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
- print_mode(level);
-
- struct rnndomain *domain = rnn_finddomain(rnn->db, "CP_DRAW_INDIRECT_MULTI");
- uint32_t count_dword = rnndec_decodereg(rnn->vc, domain, "INDIRECT_COUNT");
- uint32_t addr_dword = rnndec_decodereg(rnn->vc, domain, "INDIRECT");
- uint64_t stride_dword = rnndec_decodereg(rnn->vc, domain, "STRIDE");
-
- if (count_dword) {
- uint64_t count_addr = ((uint64_t)dwords[count_dword + 1] << 32) | dwords[count_dword];
- uint32_t *buf = hostptr(count_addr);
-
- /* Don't print more draws than this if we don't know the indirect
- * count. It's possible the user will give ~0 or some other large
- * value, expecting the GPU to fill in the draw count, and we don't
- * want to print a gazillion draws in that case:
- */
- const uint32_t max_draw_count = 0x100;
-
- /* Assume the indirect count is garbage if it's larger than this
- * (quite large) value or 0. Hopefully this catches most cases.
- */
- const uint32_t max_indirect_draw_count = 0x10000;
-
- if (buf) {
- printf("%sindirect count: %u\n", levels[level], *buf);
- if (*buf == 0 || *buf > max_indirect_draw_count) {
- /* garbage value */
- count = min(count, max_draw_count);
- } else {
- /* not garbage */
- count = min(count, *buf);
- }
- } else {
- count = min(count, max_draw_count);
- }
- }
-
- if (addr_dword && stride_dword) {
- uint64_t addr = ((uint64_t)dwords[addr_dword + 1] << 32) | dwords[addr_dword];
- uint32_t stride = dwords[stride_dword];
-
- for (unsigned i = 0; i < count; i++, addr += stride) {
- printf("%sdraw %d:\n", levels[level], i);
- dump_gpuaddr_size(addr, level, 0x10, 2);
- }
- }
-
- dump_register_summary(level);
+ uint32_t prim_type = dwords[0] & 0x1f;
+ uint32_t count = dwords[2];
+
+ do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0);
+ print_mode(level);
+
+ struct rnndomain *domain = rnn_finddomain(rnn->db, "CP_DRAW_INDIRECT_MULTI");
+ uint32_t count_dword = rnndec_decodereg(rnn->vc, domain, "INDIRECT_COUNT");
+ uint32_t addr_dword = rnndec_decodereg(rnn->vc, domain, "INDIRECT");
+ uint64_t stride_dword = rnndec_decodereg(rnn->vc, domain, "STRIDE");
+
+ if (count_dword) {
+ uint64_t count_addr =
+ ((uint64_t)dwords[count_dword + 1] << 32) | dwords[count_dword];
+ uint32_t *buf = hostptr(count_addr);
+
+ /* Don't print more draws than this if we don't know the indirect
+ * count. It's possible the user will give ~0 or some other large
+ * value, expecting the GPU to fill in the draw count, and we don't
+ * want to print a gazillion draws in that case:
+ */
+ const uint32_t max_draw_count = 0x100;
+
+ /* Assume the indirect count is garbage if it's larger than this
+ * (quite large) value or 0. Hopefully this catches most cases.
+ */
+ const uint32_t max_indirect_draw_count = 0x10000;
+
+ if (buf) {
+ printf("%sindirect count: %u\n", levels[level], *buf);
+ if (*buf == 0 || *buf > max_indirect_draw_count) {
+ /* garbage value */
+ count = min(count, max_draw_count);
+ } else {
+ /* not garbage */
+ count = min(count, *buf);
+ }
+ } else {
+ count = min(count, max_draw_count);
+ }
+ }
+
+ if (addr_dword && stride_dword) {
+ uint64_t addr =
+ ((uint64_t)dwords[addr_dword + 1] << 32) | dwords[addr_dword];
+ uint32_t stride = dwords[stride_dword];
+
+ for (unsigned i = 0; i < count; i++, addr += stride) {
+ printf("%sdraw %d:\n", levels[level], i);
+ dump_gpuaddr_size(addr, level, 0x10, 2);
+ }
+ }
+
+ dump_register_summary(level);
}
static void
cp_run_cl(uint32_t *dwords, uint32_t sizedwords, int level)
{
- do_query("COMPUTE", 1);
- dump_register_summary(level);
+ do_query("COMPUTE", 1);
+ dump_register_summary(level);
}
static void
cp_nop(uint32_t *dwords, uint32_t sizedwords, int level)
{
- const char *buf = (void *)dwords;
- int i;
+ const char *buf = (void *)dwords;
+ int i;
- if (quiet(3))
- return;
+ if (quiet(3))
+ return;
- // blob doesn't use CP_NOP for string_marker but it does
- // use it for things that end up looking like, but aren't
- // ascii chars:
- if (!options->decode_markers)
- return;
+ // blob doesn't use CP_NOP for string_marker but it does
+ // use it for things that end up looking like, but aren't
+ // ascii chars:
+ if (!options->decode_markers)
+ return;
- for (i = 0; i < 4 * sizedwords; i++) {
- if (buf[i] == '\0')
- break;
- if (isascii(buf[i]))
- printf("%c", buf[i]);
- }
- printf("\n");
+ for (i = 0; i < 4 * sizedwords; i++) {
+ if (buf[i] == '\0')
+ break;
+ if (isascii(buf[i]))
+ printf("%c", buf[i]);
+ }
+ printf("\n");
}
static void
cp_indirect(uint32_t *dwords, uint32_t sizedwords, int level)
{
- /* traverse indirect buffers */
- uint64_t ibaddr;
- uint32_t ibsize;
- uint32_t *ptr = NULL;
-
- if (is_64b()) {
- /* a5xx+.. high 32b of gpu addr, then size: */
- ibaddr = dwords[0];
- ibaddr |= ((uint64_t)dwords[1]) << 32;
- ibsize = dwords[2];
- } else {
- ibaddr = dwords[0];
- ibsize = dwords[1];
- }
-
- if (!quiet(3)) {
- if (is_64b()) {
- printf("%sibaddr:%016"PRIx64"\n", levels[level], ibaddr);
- } else {
- printf("%sibaddr:%08x\n", levels[level], (uint32_t)ibaddr);
- }
- printf("%sibsize:%08x\n", levels[level], ibsize);
- }
-
- if (options->once && has_dumped(ibaddr, enable_mask))
- return;
-
- /* 'query-compare' mode implies 'once' mode, although we need only to
- * process the cmdstream for *any* enable_mask mode, since we are
- * comparing binning vs draw reg values at the same time, ie. it is
- * not useful to process the same draw in both binning and draw pass.
- */
- if (options->query_compare && has_dumped(ibaddr, MODE_ALL))
- return;
-
- /* map gpuaddr back to hostptr: */
- ptr = hostptr(ibaddr);
-
- if (ptr) {
- /* If the GPU hung within the target IB, the trigger point will be
- * just after the current CP_INDIRECT_BUFFER. Because the IB is
- * executed but never returns. Account for this by checking if
- * the IB returned:
- */
- highlight_gpuaddr(gpuaddr(&dwords[is_64b() ? 3 : 2]));
-
- ib++;
- ibs[ib].base = ibaddr;
- ibs[ib].size = ibsize;
-
- dump_commands(ptr, ibsize, level);
- ib--;
- } else {
- fprintf(stderr, "could not find: %016"PRIx64" (%d)\n", ibaddr, ibsize);
- }
+ /* traverse indirect buffers */
+ uint64_t ibaddr;
+ uint32_t ibsize;
+ uint32_t *ptr = NULL;
+
+ if (is_64b()) {
+ /* a5xx+.. high 32b of gpu addr, then size: */
+ ibaddr = dwords[0];
+ ibaddr |= ((uint64_t)dwords[1]) << 32;
+ ibsize = dwords[2];
+ } else {
+ ibaddr = dwords[0];
+ ibsize = dwords[1];
+ }
+
+ if (!quiet(3)) {
+ if (is_64b()) {
+ printf("%sibaddr:%016" PRIx64 "\n", levels[level], ibaddr);
+ } else {
+ printf("%sibaddr:%08x\n", levels[level], (uint32_t)ibaddr);
+ }
+ printf("%sibsize:%08x\n", levels[level], ibsize);
+ }
+
+ if (options->once && has_dumped(ibaddr, enable_mask))
+ return;
+
+ /* 'query-compare' mode implies 'once' mode, although we need only to
+ * process the cmdstream for *any* enable_mask mode, since we are
+ * comparing binning vs draw reg values at the same time, ie. it is
+ * not useful to process the same draw in both binning and draw pass.
+ */
+ if (options->query_compare && has_dumped(ibaddr, MODE_ALL))
+ return;
+
+ /* map gpuaddr back to hostptr: */
+ ptr = hostptr(ibaddr);
+
+ if (ptr) {
+ /* If the GPU hung within the target IB, the trigger point will be
+ * just after the current CP_INDIRECT_BUFFER. Because the IB is
+ * executed but never returns. Account for this by checking if
+ * the IB returned:
+ */
+ highlight_gpuaddr(gpuaddr(&dwords[is_64b() ? 3 : 2]));
+
+ ib++;
+ ibs[ib].base = ibaddr;
+ ibs[ib].size = ibsize;
+
+ dump_commands(ptr, ibsize, level);
+ ib--;
+ } else {
+ fprintf(stderr, "could not find: %016" PRIx64 " (%d)\n", ibaddr, ibsize);
+ }
}
static void
cp_wfi(uint32_t *dwords, uint32_t sizedwords, int level)
{
- needs_wfi = false;
+ needs_wfi = false;
}
static void
cp_mem_write(uint32_t *dwords, uint32_t sizedwords, int level)
{
- if (quiet(2))
- return;
+ if (quiet(2))
+ return;
- if (is_64b()) {
- uint64_t gpuaddr = dwords[0] | (((uint64_t)dwords[1]) << 32);
- printf("%sgpuaddr:%016"PRIx64"\n", levels[level], gpuaddr);
- dump_hex(&dwords[2], sizedwords-2, level+1);
+ if (is_64b()) {
+ uint64_t gpuaddr = dwords[0] | (((uint64_t)dwords[1]) << 32);
+ printf("%sgpuaddr:%016" PRIx64 "\n", levels[level], gpuaddr);
+ dump_hex(&dwords[2], sizedwords - 2, level + 1);
- if (pkt_is_type4(dwords[2]) || pkt_is_type7(dwords[2]))
- dump_commands(&dwords[2], sizedwords-2, level+1);
- } else {
- uint32_t gpuaddr = dwords[0];
- printf("%sgpuaddr:%08x\n", levels[level], gpuaddr);
- dump_float((float *)&dwords[1], sizedwords-1, level+1);
- }
+ if (pkt_is_type4(dwords[2]) || pkt_is_type7(dwords[2]))
+ dump_commands(&dwords[2], sizedwords - 2, level + 1);
+ } else {
+ uint32_t gpuaddr = dwords[0];
+ printf("%sgpuaddr:%08x\n", levels[level], gpuaddr);
+ dump_float((float *)&dwords[1], sizedwords - 1, level + 1);
+ }
}
static void
cp_rmw(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t val = dwords[0] & 0xffff;
- uint32_t and = dwords[1];
- uint32_t or = dwords[2];
- printl(3, "%srmw (%s & 0x%08x) | 0x%08x)\n", levels[level], regname(val, 1), and, or);
- if (needs_wfi)
- printl(2, "NEEDS WFI: rmw (%s & 0x%08x) | 0x%08x)\n", regname(val, 1), and, or);
- reg_set(val, (reg_val(val) & and) | or);
+ uint32_t val = dwords[0] & 0xffff;
+ uint32_t and = dwords[1];
+ uint32_t or = dwords[2];
+ printl(3, "%srmw (%s & 0x%08x) | 0x%08x)\n", levels[level], regname(val, 1),
+ and, or);
+ if (needs_wfi)
+ printl(2, "NEEDS WFI: rmw (%s & 0x%08x) | 0x%08x)\n", regname(val, 1),
+ and, or);
+ reg_set(val, (reg_val(val) & and) | or);
}
static void
cp_reg_mem(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t val = dwords[0] & 0xffff;
- printl(3, "%sbase register: %s\n", levels[level], regname(val, 1));
+ uint32_t val = dwords[0] & 0xffff;
+ printl(3, "%sbase register: %s\n", levels[level], regname(val, 1));
- if (quiet(2))
- return;
+ if (quiet(2))
+ return;
- uint64_t gpuaddr = dwords[1] | (((uint64_t)dwords[2]) << 32);
- printf("%sgpuaddr:%016"PRIx64"\n", levels[level], gpuaddr);
- void *ptr = hostptr(gpuaddr);
- if (ptr) {
- uint32_t cnt = (dwords[0] >> 19) & 0x3ff;
- dump_hex(ptr, cnt, level + 1);
- }
+ uint64_t gpuaddr = dwords[1] | (((uint64_t)dwords[2]) << 32);
+ printf("%sgpuaddr:%016" PRIx64 "\n", levels[level], gpuaddr);
+ void *ptr = hostptr(gpuaddr);
+ if (ptr) {
+ uint32_t cnt = (dwords[0] >> 19) & 0x3ff;
+ dump_hex(ptr, cnt, level + 1);
+ }
}
struct draw_state {
- uint16_t enable_mask;
- uint16_t flags;
- uint32_t count;
- uint64_t addr;
+ uint16_t enable_mask;
+ uint16_t flags;
+ uint32_t count;
+ uint64_t addr;
};
struct draw_state state[32];
@@ -2248,384 +2267,386 @@ static int draw_mode;
static void
disable_group(unsigned group_id)
{
- struct draw_state *ds = &state[group_id];
- memset(ds, 0, sizeof(*ds));
+ struct draw_state *ds = &state[group_id];
+ memset(ds, 0, sizeof(*ds));
}
static void
disable_all_groups(void)
{
- for (unsigned i = 0; i < ARRAY_SIZE(state); i++)
- disable_group(i);
+ for (unsigned i = 0; i < ARRAY_SIZE(state); i++)
+ disable_group(i);
}
static void
load_group(unsigned group_id, int level)
{
- struct draw_state *ds = &state[group_id];
+ struct draw_state *ds = &state[group_id];
- if (!ds->count)
- return;
+ if (!ds->count)
+ return;
- printl(2, "%sgroup_id: %u\n", levels[level], group_id);
- printl(2, "%scount: %d\n", levels[level], ds->count);
- printl(2, "%saddr: %016llx\n", levels[level], ds->addr);
- printl(2, "%sflags: %x\n", levels[level], ds->flags);
+ printl(2, "%sgroup_id: %u\n", levels[level], group_id);
+ printl(2, "%scount: %d\n", levels[level], ds->count);
+ printl(2, "%saddr: %016llx\n", levels[level], ds->addr);
+ printl(2, "%sflags: %x\n", levels[level], ds->flags);
- if (options->gpu_id >= 600) {
- printl(2, "%senable_mask: 0x%x\n", levels[level], ds->enable_mask);
+ if (options->gpu_id >= 600) {
+ printl(2, "%senable_mask: 0x%x\n", levels[level], ds->enable_mask);
- if (!(ds->enable_mask & enable_mask)) {
- printl(2, "%s\tskipped!\n\n", levels[level]);
- return;
- }
- }
+ if (!(ds->enable_mask & enable_mask)) {
+ printl(2, "%s\tskipped!\n\n", levels[level]);
+ return;
+ }
+ }
- void *ptr = hostptr(ds->addr);
- if (ptr) {
- if (!quiet(2))
- dump_hex(ptr, ds->count, level+1);
+ void *ptr = hostptr(ds->addr);
+ if (ptr) {
+ if (!quiet(2))
+ dump_hex(ptr, ds->count, level + 1);
- ib++;
- dump_commands(ptr, ds->count, level+1);
- ib--;
- }
+ ib++;
+ dump_commands(ptr, ds->count, level + 1);
+ ib--;
+ }
}
static void
load_all_groups(int level)
{
- /* sanity check, we should never recursively hit recursion here, and if
- * we do bad things happen:
- */
- static bool loading_groups = false;
- if (loading_groups) {
- printf("ERROR: nothing in draw state should trigger recursively loading groups!\n");
- return;
- }
- loading_groups = true;
- for (unsigned i = 0; i < ARRAY_SIZE(state); i++)
- load_group(i, level);
- loading_groups = false;
+ /* sanity check, we should never recursively hit recursion here, and if
+ * we do bad things happen:
+ */
+ static bool loading_groups = false;
+ if (loading_groups) {
+ printf("ERROR: nothing in draw state should trigger recursively loading "
+ "groups!\n");
+ return;
+ }
+ loading_groups = true;
+ for (unsigned i = 0; i < ARRAY_SIZE(state); i++)
+ load_group(i, level);
+ loading_groups = false;
- /* in 'query-compare' mode, defer disabling all groups until we have a
- * chance to process the query:
- */
- if (!options->query_compare)
- disable_all_groups();
+ /* in 'query-compare' mode, defer disabling all groups until we have a
+ * chance to process the query:
+ */
+ if (!options->query_compare)
+ disable_all_groups();
}
static void
cp_set_draw_state(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t i;
+ uint32_t i;
- for (i = 0; i < sizedwords; ) {
- struct draw_state *ds;
- uint32_t count = dwords[i] & 0xffff;
- uint32_t group_id = (dwords[i] >> 24) & 0x1f;
- uint32_t enable_mask = (dwords[i] >> 20) & 0xf;
- uint32_t flags = (dwords[i] >> 16) & 0xf;
- uint64_t addr;
+ for (i = 0; i < sizedwords;) {
+ struct draw_state *ds;
+ uint32_t count = dwords[i] & 0xffff;
+ uint32_t group_id = (dwords[i] >> 24) & 0x1f;
+ uint32_t enable_mask = (dwords[i] >> 20) & 0xf;
+ uint32_t flags = (dwords[i] >> 16) & 0xf;
+ uint64_t addr;
- if (is_64b()) {
- addr = dwords[i + 1];
- addr |= ((uint64_t)dwords[i + 2]) << 32;
- i += 3;
- } else {
- addr = dwords[i + 1];
- i += 2;
- }
+ if (is_64b()) {
+ addr = dwords[i + 1];
+ addr |= ((uint64_t)dwords[i + 2]) << 32;
+ i += 3;
+ } else {
+ addr = dwords[i + 1];
+ i += 2;
+ }
- if (flags & FLAG_DISABLE_ALL_GROUPS) {
- disable_all_groups();
- continue;
- }
+ if (flags & FLAG_DISABLE_ALL_GROUPS) {
+ disable_all_groups();
+ continue;
+ }
- if (flags & FLAG_DISABLE) {
- disable_group(group_id);
- continue;
- }
+ if (flags & FLAG_DISABLE) {
+ disable_group(group_id);
+ continue;
+ }
- assert(group_id < ARRAY_SIZE(state));
- disable_group(group_id);
+ assert(group_id < ARRAY_SIZE(state));
+ disable_group(group_id);
- ds = &state[group_id];
+ ds = &state[group_id];
- ds->enable_mask = enable_mask;
- ds->flags = flags;
- ds->count = count;
- ds->addr = addr;
+ ds->enable_mask = enable_mask;
+ ds->flags = flags;
+ ds->count = count;
+ ds->addr = addr;
- if (flags & FLAG_LOAD_IMMED) {
- load_group(group_id, level);
- disable_group(group_id);
- }
- }
+ if (flags & FLAG_LOAD_IMMED) {
+ load_group(group_id, level);
+ disable_group(group_id);
+ }
+ }
}
static void
cp_set_mode(uint32_t *dwords, uint32_t sizedwords, int level)
{
- draw_mode = dwords[0];
+ draw_mode = dwords[0];
}
/* execute compute shader */
static void
cp_exec_cs(uint32_t *dwords, uint32_t sizedwords, int level)
{
- do_query("compute", 0);
- dump_register_summary(level);
+ do_query("compute", 0);
+ dump_register_summary(level);
}
static void
cp_exec_cs_indirect(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint64_t addr;
+ uint64_t addr;
- if (is_64b()) {
- addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
- } else {
- addr = dwords[1];
- }
+ if (is_64b()) {
+ addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1];
+ } else {
+ addr = dwords[1];
+ }
- printl(3, "%saddr: %016llx\n", levels[level], addr);
- dump_gpuaddr_size(addr, level, 0x10, 2);
+ printl(3, "%saddr: %016llx\n", levels[level], addr);
+ dump_gpuaddr_size(addr, level, 0x10, 2);
- do_query("compute", 0);
- dump_register_summary(level);
+ do_query("compute", 0);
+ dump_register_summary(level);
}
static void
cp_set_marker(uint32_t *dwords, uint32_t sizedwords, int level)
{
- render_mode = rnn_enumname(rnn, "a6xx_render_mode", dwords[0] & 0xf);
+ render_mode = rnn_enumname(rnn, "a6xx_render_mode", dwords[0] & 0xf);
- if (!strcmp(render_mode, "RM6_BINNING")) {
- enable_mask = MODE_BINNING;
- } else if (!strcmp(render_mode, "RM6_GMEM")) {
- enable_mask = MODE_GMEM;
- } else if (!strcmp(render_mode, "RM6_BYPASS")) {
- enable_mask = MODE_BYPASS;
- }
+ if (!strcmp(render_mode, "RM6_BINNING")) {
+ enable_mask = MODE_BINNING;
+ } else if (!strcmp(render_mode, "RM6_GMEM")) {
+ enable_mask = MODE_GMEM;
+ } else if (!strcmp(render_mode, "RM6_BYPASS")) {
+ enable_mask = MODE_BYPASS;
+ }
}
static void
cp_set_render_mode(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint64_t addr;
- uint32_t *ptr, len;
+ uint64_t addr;
+ uint32_t *ptr, len;
- assert(is_64b());
+ assert(is_64b());
- /* TODO seems to have two ptrs, 9 dwords total (incl pkt7 hdr)..
- * not sure if this can come in different sizes.
- *
- * First ptr doesn't seem to be cmdstream, second one does.
- *
- * Comment from downstream kernel:
- *
- * SRM -- set render mode (ex binning, direct render etc)
- * SRM is set by UMD usually at start of IB to tell CP the type of
- * preemption.
- * KMD needs to set SRM to NULL to indicate CP that rendering is
- * done by IB.
- * ------------------------------------------------------------------
- *
- * Seems to always be one of these two:
- * 70ec0008 00000001 001c0000 00000000 00000010 00000003 0000000d 001c2000 00000000
- * 70ec0008 00000001 001c0000 00000000 00000000 00000003 0000000d 001c2000 00000000
- *
- */
+ /* TODO seems to have two ptrs, 9 dwords total (incl pkt7 hdr)..
+ * not sure if this can come in different sizes.
+ *
+ * First ptr doesn't seem to be cmdstream, second one does.
+ *
+ * Comment from downstream kernel:
+ *
+ * SRM -- set render mode (ex binning, direct render etc)
+ * SRM is set by UMD usually at start of IB to tell CP the type of
+ * preemption.
+ * KMD needs to set SRM to NULL to indicate CP that rendering is
+ * done by IB.
+ * ------------------------------------------------------------------
+ *
+ * Seems to always be one of these two:
+ * 70ec0008 00000001 001c0000 00000000 00000010 00000003 0000000d 001c2000
+ * 00000000 70ec0008 00000001 001c0000 00000000 00000000 00000003 0000000d
+ * 001c2000 00000000
+ *
+ */
- assert(options->gpu_id >= 500);
+ assert(options->gpu_id >= 500);
- render_mode = rnn_enumname(rnn, "render_mode_cmd", dwords[0]);
+ render_mode = rnn_enumname(rnn, "render_mode_cmd", dwords[0]);
- if (sizedwords == 1)
- return;
+ if (sizedwords == 1)
+ return;
- addr = dwords[1];
- addr |= ((uint64_t)dwords[2]) << 32;
+ addr = dwords[1];
+ addr |= ((uint64_t)dwords[2]) << 32;
- mode = dwords[3];
+ mode = dwords[3];
- dump_gpuaddr(addr, level+1);
+ dump_gpuaddr(addr, level + 1);
- if (sizedwords == 5)
- return;
+ if (sizedwords == 5)
+ return;
- assert(sizedwords == 8);
+ assert(sizedwords == 8);
- len = dwords[5];
- addr = dwords[6];
- addr |= ((uint64_t)dwords[7]) << 32;
+ len = dwords[5];
+ addr = dwords[6];
+ addr |= ((uint64_t)dwords[7]) << 32;
- printl(3, "%saddr: 0x%016lx\n", levels[level], addr);
- printl(3, "%slen: 0x%x\n", levels[level], len);
+ printl(3, "%saddr: 0x%016lx\n", levels[level], addr);
+ printl(3, "%slen: 0x%x\n", levels[level], len);
- ptr = hostptr(addr);
+ ptr = hostptr(addr);
- if (ptr) {
- if (!quiet(2)) {
- ib++;
- dump_commands(ptr, len, level+1);
- ib--;
- dump_hex(ptr, len, level+1);
- }
- }
+ if (ptr) {
+ if (!quiet(2)) {
+ ib++;
+ dump_commands(ptr, len, level + 1);
+ ib--;
+ dump_hex(ptr, len, level + 1);
+ }
+ }
}
static void
cp_compute_checkpoint(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint64_t addr;
- uint32_t *ptr, len;
+ uint64_t addr;
+ uint32_t *ptr, len;
- assert(is_64b());
- assert(options->gpu_id >= 500);
+ assert(is_64b());
+ assert(options->gpu_id >= 500);
- assert(sizedwords == 8);
+ assert(sizedwords == 8);
- addr = dwords[5];
- addr |= ((uint64_t)dwords[6]) << 32;
- len = dwords[7];
+ addr = dwords[5];
+ addr |= ((uint64_t)dwords[6]) << 32;
+ len = dwords[7];
- printl(3, "%saddr: 0x%016"PRIx64"\n", levels[level], addr);
- printl(3, "%slen: 0x%x\n", levels[level], len);
+ printl(3, "%saddr: 0x%016" PRIx64 "\n", levels[level], addr);
+ printl(3, "%slen: 0x%x\n", levels[level], len);
- ptr = hostptr(addr);
+ ptr = hostptr(addr);
- if (ptr) {
- if (!quiet(2)) {
- ib++;
- dump_commands(ptr, len, level+1);
- ib--;
- dump_hex(ptr, len, level+1);
- }
- }
+ if (ptr) {
+ if (!quiet(2)) {
+ ib++;
+ dump_commands(ptr, len, level + 1);
+ ib--;
+ dump_hex(ptr, len, level + 1);
+ }
+ }
}
static void
cp_blit(uint32_t *dwords, uint32_t sizedwords, int level)
{
- do_query(rnn_enumname(rnn, "cp_blit_cmd", dwords[0]), 0);
- print_mode(level);
- dump_register_summary(level);
+ do_query(rnn_enumname(rnn, "cp_blit_cmd", dwords[0]), 0);
+ print_mode(level);
+ dump_register_summary(level);
}
static void
cp_context_reg_bunch(uint32_t *dwords, uint32_t sizedwords, int level)
{
- int i;
+ int i;
- /* NOTE: seems to write same reg multiple times.. not sure if different parts of
- * these are triggered by the FLUSH_SO_n events?? (if that is what they actually
- * are?)
- */
- bool saved_summary = summary;
- summary = false;
+ /* NOTE: seems to write same reg multiple times.. not sure if different parts
+ * of these are triggered by the FLUSH_SO_n events?? (if that is what they
+ * actually are?)
+ */
+ bool saved_summary = summary;
+ summary = false;
- for (i = 0; i < sizedwords; i += 2) {
- dump_register(dwords[i+0], dwords[i+1], level+1);
- reg_set(dwords[i+0], dwords[i+1]);
- }
+ for (i = 0; i < sizedwords; i += 2) {
+ dump_register(dwords[i + 0], dwords[i + 1], level + 1);
+ reg_set(dwords[i + 0], dwords[i + 1]);
+ }
- summary = saved_summary;
+ summary = saved_summary;
}
static void
cp_reg_write(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint32_t reg = dwords[1] & 0xffff;
+ uint32_t reg = dwords[1] & 0xffff;
- dump_register(reg, dwords[2], level+1);
- reg_set(reg, dwords[2]);
+ dump_register(reg, dwords[2], level + 1);
+ reg_set(reg, dwords[2]);
}
static void
cp_set_ctxswitch_ib(uint32_t *dwords, uint32_t sizedwords, int level)
{
- uint64_t addr;
- uint32_t size = dwords[2] & 0xffff;
- void *ptr;
+ uint64_t addr;
+ uint32_t size = dwords[2] & 0xffff;
+ void *ptr;
- addr = dwords[0] | ((uint64_t)dwords[1] << 32);
+ addr = dwords[0] | ((uint64_t)dwords[1] << 32);
- printf("addr=%"PRIx64"\n", addr);
- ptr = hostptr(addr);
- if (ptr) {
- dump_commands(ptr, size, level+1);
- }
+ printf("addr=%" PRIx64 "\n", addr);
+ ptr = hostptr(addr);
+ if (ptr) {
+ dump_commands(ptr, size, level + 1);
+ }
}
static void
cp_skip_ib2_enable_global(uint32_t *dwords, uint32_t sizedwords, int level)
{
- skip_ib2_enable_global = dwords[0];
+ skip_ib2_enable_global = dwords[0];
}
static void
cp_skip_ib2_enable_local(uint32_t *dwords, uint32_t sizedwords, int level)
{
- skip_ib2_enable_local = dwords[0];
+ skip_ib2_enable_local = dwords[0];
}
-#define CP(x, fxn, ...) { "CP_" #x, fxn, ##__VA_ARGS__ }
+#define CP(x, fxn, ...) { "CP_" #x, fxn, ##__VA_ARGS__ }
static const struct type3_op {
- const char *name;
- void (*fxn)(uint32_t *dwords, uint32_t sizedwords, int level);
- struct {
- bool load_all_groups;
- } options;
+ const char *name;
+ void (*fxn)(uint32_t *dwords, uint32_t sizedwords, int level);
+ struct {
+ bool load_all_groups;
+ } options;
} type3_op[] = {
- CP(NOP, cp_nop),
- CP(INDIRECT_BUFFER, cp_indirect),
- CP(INDIRECT_BUFFER_PFD, cp_indirect),
- CP(WAIT_FOR_IDLE, cp_wfi),
- CP(REG_RMW, cp_rmw),
- CP(REG_TO_MEM, cp_reg_mem),
- CP(MEM_TO_REG, cp_reg_mem), /* same layout as CP_REG_TO_MEM */
- CP(MEM_WRITE, cp_mem_write),
- CP(EVENT_WRITE, cp_event_write),
- CP(RUN_OPENCL, cp_run_cl),
- CP(DRAW_INDX, cp_draw_indx, {.load_all_groups=true}),
- CP(DRAW_INDX_2, cp_draw_indx_2, {.load_all_groups=true}),
- CP(SET_CONSTANT, cp_set_const),
- CP(IM_LOAD_IMMEDIATE, cp_im_loadi),
- CP(WIDE_REG_WRITE, cp_wide_reg_write),
-
- /* for a3xx */
- CP(LOAD_STATE, cp_load_state),
- CP(SET_BIN, cp_set_bin),
-
- /* for a4xx */
- CP(LOAD_STATE4, cp_load_state),
- CP(SET_DRAW_STATE, cp_set_draw_state),
- CP(DRAW_INDX_OFFSET, cp_draw_indx_offset, {.load_all_groups=true}),
- CP(EXEC_CS, cp_exec_cs, {.load_all_groups=true}),
- CP(EXEC_CS_INDIRECT, cp_exec_cs_indirect, {.load_all_groups=true}),
-
- /* for a5xx */
- CP(SET_RENDER_MODE, cp_set_render_mode),
- CP(COMPUTE_CHECKPOINT, cp_compute_checkpoint),
- CP(BLIT, cp_blit),
- CP(CONTEXT_REG_BUNCH, cp_context_reg_bunch),
- CP(DRAW_INDIRECT, cp_draw_indirect, {.load_all_groups=true}),
- CP(DRAW_INDX_INDIRECT, cp_draw_indx_indirect, {.load_all_groups=true}),
- CP(DRAW_INDIRECT_MULTI, cp_draw_indirect_multi, {.load_all_groups=true}),
- CP(SKIP_IB2_ENABLE_GLOBAL, cp_skip_ib2_enable_global),
- CP(SKIP_IB2_ENABLE_LOCAL, cp_skip_ib2_enable_local),
-
- /* for a6xx */
- CP(LOAD_STATE6_GEOM, cp_load_state),
- CP(LOAD_STATE6_FRAG, cp_load_state),
- CP(LOAD_STATE6, cp_load_state),
- CP(SET_MODE, cp_set_mode),
- CP(SET_MARKER, cp_set_marker),
- CP(REG_WRITE, cp_reg_write),
-
- CP(SET_CTXSWITCH_IB, cp_set_ctxswitch_ib),
+ CP(NOP, cp_nop),
+ CP(INDIRECT_BUFFER, cp_indirect),
+ CP(INDIRECT_BUFFER_PFD, cp_indirect),
+ CP(WAIT_FOR_IDLE, cp_wfi),
+ CP(REG_RMW, cp_rmw),
+ CP(REG_TO_MEM, cp_reg_mem),
+ CP(MEM_TO_REG, cp_reg_mem), /* same layout as CP_REG_TO_MEM */
+ CP(MEM_WRITE, cp_mem_write),
+ CP(EVENT_WRITE, cp_event_write),
+ CP(RUN_OPENCL, cp_run_cl),
+ CP(DRAW_INDX, cp_draw_indx, {.load_all_groups = true}),
+ CP(DRAW_INDX_2, cp_draw_indx_2, {.load_all_groups = true}),
+ CP(SET_CONSTANT, cp_set_const),
+ CP(IM_LOAD_IMMEDIATE, cp_im_loadi),
+ CP(WIDE_REG_WRITE, cp_wide_reg_write),
+
+ /* for a3xx */
+ CP(LOAD_STATE, cp_load_state),
+ CP(SET_BIN, cp_set_bin),
+
+ /* for a4xx */
+ CP(LOAD_STATE4, cp_load_state),
+ CP(SET_DRAW_STATE, cp_set_draw_state),
+ CP(DRAW_INDX_OFFSET, cp_draw_indx_offset, {.load_all_groups = true}),
+ CP(EXEC_CS, cp_exec_cs, {.load_all_groups = true}),
+ CP(EXEC_CS_INDIRECT, cp_exec_cs_indirect, {.load_all_groups = true}),
+
+ /* for a5xx */
+ CP(SET_RENDER_MODE, cp_set_render_mode),
+ CP(COMPUTE_CHECKPOINT, cp_compute_checkpoint),
+ CP(BLIT, cp_blit),
+ CP(CONTEXT_REG_BUNCH, cp_context_reg_bunch),
+ CP(DRAW_INDIRECT, cp_draw_indirect, {.load_all_groups = true}),
+ CP(DRAW_INDX_INDIRECT, cp_draw_indx_indirect, {.load_all_groups = true}),
+ CP(DRAW_INDIRECT_MULTI, cp_draw_indirect_multi, {.load_all_groups = true}),
+ CP(SKIP_IB2_ENABLE_GLOBAL, cp_skip_ib2_enable_global),
+ CP(SKIP_IB2_ENABLE_LOCAL, cp_skip_ib2_enable_local),
+
+ /* for a6xx */
+ CP(LOAD_STATE6_GEOM, cp_load_state),
+ CP(LOAD_STATE6_FRAG, cp_load_state),
+ CP(LOAD_STATE6, cp_load_state),
+ CP(SET_MODE, cp_set_mode),
+ CP(SET_MARKER, cp_set_marker),
+ CP(REG_WRITE, cp_reg_write),
+
+ CP(SET_CTXSWITCH_IB, cp_set_ctxswitch_ib),
};
static void
@@ -2636,153 +2657,154 @@ noop_fxn(uint32_t *dwords, uint32_t sizedwords, int level)
static const struct type3_op *
get_type3_op(unsigned opc)
{
- static const struct type3_op dummy_op = {
- .fxn = noop_fxn,
- };
- const char *name = pktname(opc);
+ static const struct type3_op dummy_op = {
+ .fxn = noop_fxn,
+ };
+ const char *name = pktname(opc);
- if (!name)
- return &dummy_op;
+ if (!name)
+ return &dummy_op;
- for (unsigned i = 0; i < ARRAY_SIZE(type3_op); i++)
- if (!strcmp(name, type3_op[i].name))
- return &type3_op[i];
+ for (unsigned i = 0; i < ARRAY_SIZE(type3_op); i++)
+ if (!strcmp(name, type3_op[i].name))
+ return &type3_op[i];
- return &dummy_op;
+ return &dummy_op;
}
void
dump_commands(uint32_t *dwords, uint32_t sizedwords, int level)
{
- int dwords_left = sizedwords;
- uint32_t count = 0; /* dword count including packet header */
- uint32_t val;
-
-// assert(dwords);
- if (!dwords) {
- printf("NULL cmd buffer!\n");
- return;
- }
-
- assert(ib < ARRAY_SIZE(draws));
- draws[ib] = 0;
-
- while (dwords_left > 0) {
-
- current_draw_count = draw_count;
-
- /* hack, this looks like a -1 underflow, in some versions
- * when it tries to write zero registers via pkt0
- */
-// if ((dwords[0] >> 16) == 0xffff)
-// goto skip;
-
- if (pkt_is_type0(dwords[0])) {
- printl(3, "t0");
- count = type0_pkt_size(dwords[0]) + 1;
- val = type0_pkt_offset(dwords[0]);
- assert(val < regcnt());
- printl(3, "%swrite %s%s (%04x)\n", levels[level+1], regname(val, 1),
- (dwords[0] & 0x8000) ? " (same register)" : "", val);
- dump_registers(val, dwords+1, count-1, level+2);
- if (!quiet(3))
- dump_hex(dwords, count, level+1);
- } else if (pkt_is_type4(dwords[0])) {
- /* basically the same(ish) as type0 prior to a5xx */
- printl(3, "t4");
- count = type4_pkt_size(dwords[0]) + 1;
- val = type4_pkt_offset(dwords[0]);
- assert(val < regcnt());
- printl(3, "%swrite %s (%04x)\n", levels[level+1], regname(val, 1), val);
- dump_registers(val, dwords+1, count-1, level+2);
- if (!quiet(3))
- dump_hex(dwords, count, level+1);
+ int dwords_left = sizedwords;
+ uint32_t count = 0; /* dword count including packet header */
+ uint32_t val;
+
+ // assert(dwords);
+ if (!dwords) {
+ printf("NULL cmd buffer!\n");
+ return;
+ }
+
+ assert(ib < ARRAY_SIZE(draws));
+ draws[ib] = 0;
+
+ while (dwords_left > 0) {
+
+ current_draw_count = draw_count;
+
+ /* hack, this looks like a -1 underflow, in some versions
+ * when it tries to write zero registers via pkt0
+ */
+ // if ((dwords[0] >> 16) == 0xffff)
+ // goto skip;
+
+ if (pkt_is_type0(dwords[0])) {
+ printl(3, "t0");
+ count = type0_pkt_size(dwords[0]) + 1;
+ val = type0_pkt_offset(dwords[0]);
+ assert(val < regcnt());
+ printl(3, "%swrite %s%s (%04x)\n", levels[level + 1], regname(val, 1),
+ (dwords[0] & 0x8000) ? " (same register)" : "", val);
+ dump_registers(val, dwords + 1, count - 1, level + 2);
+ if (!quiet(3))
+ dump_hex(dwords, count, level + 1);
+ } else if (pkt_is_type4(dwords[0])) {
+ /* basically the same(ish) as type0 prior to a5xx */
+ printl(3, "t4");
+ count = type4_pkt_size(dwords[0]) + 1;
+ val = type4_pkt_offset(dwords[0]);
+ assert(val < regcnt());
+ printl(3, "%swrite %s (%04x)\n", levels[level + 1], regname(val, 1),
+ val);
+ dump_registers(val, dwords + 1, count - 1, level + 2);
+ if (!quiet(3))
+ dump_hex(dwords, count, level + 1);
#if 0
- } else if (pkt_is_type1(dwords[0])) {
- printl(3, "t1");
- count = 3;
- val = dwords[0] & 0xfff;
- printl(3, "%swrite %s\n", levels[level+1], regname(val, 1));
- dump_registers(val, dwords+1, 1, level+2);
- val = (dwords[0] >> 12) & 0xfff;
- printl(3, "%swrite %s\n", levels[level+1], regname(val, 1));
- dump_registers(val, dwords+2, 1, level+2);
- if (!quiet(3))
- dump_hex(dwords, count, level+1);
- } else if (pkt_is_type2(dwords[0])) {
- printl(3, "t2");
- printf("%sNOP\n", levels[level+1]);
- count = 1;
- if (!quiet(3))
- dump_hex(dwords, count, level+1);
+ } else if (pkt_is_type1(dwords[0])) {
+ printl(3, "t1");
+ count = 3;
+ val = dwords[0] & 0xfff;
+ printl(3, "%swrite %s\n", levels[level+1], regname(val, 1));
+ dump_registers(val, dwords+1, 1, level+2);
+ val = (dwords[0] >> 12) & 0xfff;
+ printl(3, "%swrite %s\n", levels[level+1], regname(val, 1));
+ dump_registers(val, dwords+2, 1, level+2);
+ if (!quiet(3))
+ dump_hex(dwords, count, level+1);
+ } else if (pkt_is_type2(dwords[0])) {
+ printl(3, "t2");
+ printf("%sNOP\n", levels[level+1]);
+ count = 1;
+ if (!quiet(3))
+ dump_hex(dwords, count, level+1);
#endif
- } else if (pkt_is_type3(dwords[0])) {
- count = type3_pkt_size(dwords[0]) + 1;
- val = cp_type3_opcode(dwords[0]);
- const struct type3_op *op = get_type3_op(val);
- if (op->options.load_all_groups)
- load_all_groups(level+1);
- printl(3, "t3");
- const char *name = pktname(val);
- if (!quiet(2)) {
- printf("\t%sopcode: %s%s%s (%02x) (%d dwords)%s\n", levels[level],
- rnn->vc->colors->bctarg, name, rnn->vc->colors->reset,
- val, count, (dwords[0] & 0x1) ? " (predicated)" : "");
- }
- if (name)
- dump_domain(dwords+1, count-1, level+2, name);
- op->fxn(dwords+1, count-1, level+1);
- if (!quiet(2))
- dump_hex(dwords, count, level+1);
- } else if (pkt_is_type7(dwords[0])) {
- count = type7_pkt_size(dwords[0]) + 1;
- val = cp_type7_opcode(dwords[0]);
- const struct type3_op *op = get_type3_op(val);
- if (op->options.load_all_groups)
- load_all_groups(level+1);
- printl(3, "t7");
- const char *name = pktname(val);
- if (!quiet(2)) {
- printf("\t%sopcode: %s%s%s (%02x) (%d dwords)\n", levels[level],
- rnn->vc->colors->bctarg, name, rnn->vc->colors->reset,
- val, count);
- }
- if (name) {
- /* special hack for two packets that decode the same way
- * on a6xx:
- */
- if (!strcmp(name, "CP_LOAD_STATE6_FRAG") ||
- !strcmp(name, "CP_LOAD_STATE6_GEOM"))
- name = "CP_LOAD_STATE6";
- dump_domain(dwords+1, count-1, level+2, name);
- }
- op->fxn(dwords+1, count-1, level+1);
- if (!quiet(2))
- dump_hex(dwords, count, level+1);
- } else if (pkt_is_type2(dwords[0])) {
- printl(3, "t2");
- printl(3, "%snop\n", levels[level+1]);
- } else {
- /* for 5xx+ we can do a passable job of looking for start of next valid packet: */
- if (options->gpu_id >= 500) {
- while (dwords_left > 0) {
- if (pkt_is_type7(dwords[0]) || pkt_is_type4(dwords[0]))
- break;
- printf("bad type! %08x\n", dwords[0]);
- dwords++;
- dwords_left--;
- }
- } else {
- printf("bad type! %08x\n", dwords[0]);
- return;
- }
- }
-
- dwords += count;
- dwords_left -= count;
-
- }
-
- if (dwords_left < 0)
- printf("**** this ain't right!! dwords_left=%d\n", dwords_left);
+ } else if (pkt_is_type3(dwords[0])) {
+ count = type3_pkt_size(dwords[0]) + 1;
+ val = cp_type3_opcode(dwords[0]);
+ const struct type3_op *op = get_type3_op(val);
+ if (op->options.load_all_groups)
+ load_all_groups(level + 1);
+ printl(3, "t3");
+ const char *name = pktname(val);
+ if (!quiet(2)) {
+ printf("\t%sopcode: %s%s%s (%02x) (%d dwords)%s\n", levels[level],
+ rnn->vc->colors->bctarg, name, rnn->vc->colors->reset, val,
+ count, (dwords[0] & 0x1) ? " (predicated)" : "");
+ }
+ if (name)
+ dump_domain(dwords + 1, count - 1, level + 2, name);
+ op->fxn(dwords + 1, count - 1, level + 1);
+ if (!quiet(2))
+ dump_hex(dwords, count, level + 1);
+ } else if (pkt_is_type7(dwords[0])) {
+ count = type7_pkt_size(dwords[0]) + 1;
+ val = cp_type7_opcode(dwords[0]);
+ const struct type3_op *op = get_type3_op(val);
+ if (op->options.load_all_groups)
+ load_all_groups(level + 1);
+ printl(3, "t7");
+ const char *name = pktname(val);
+ if (!quiet(2)) {
+ printf("\t%sopcode: %s%s%s (%02x) (%d dwords)\n", levels[level],
+ rnn->vc->colors->bctarg, name, rnn->vc->colors->reset, val,
+ count);
+ }
+ if (name) {
+ /* special hack for two packets that decode the same way
+ * on a6xx:
+ */
+ if (!strcmp(name, "CP_LOAD_STATE6_FRAG") ||
+ !strcmp(name, "CP_LOAD_STATE6_GEOM"))
+ name = "CP_LOAD_STATE6";
+ dump_domain(dwords + 1, count - 1, level + 2, name);
+ }
+ op->fxn(dwords + 1, count - 1, level + 1);
+ if (!quiet(2))
+ dump_hex(dwords, count, level + 1);
+ } else if (pkt_is_type2(dwords[0])) {
+ printl(3, "t2");
+ printl(3, "%snop\n", levels[level + 1]);
+ } else {
+ /* for 5xx+ we can do a passable job of looking for start of next valid
+ * packet: */
+ if (options->gpu_id >= 500) {
+ while (dwords_left > 0) {
+ if (pkt_is_type7(dwords[0]) || pkt_is_type4(dwords[0]))
+ break;
+ printf("bad type! %08x\n", dwords[0]);
+ dwords++;
+ dwords_left--;
+ }
+ } else {
+ printf("bad type! %08x\n", dwords[0]);
+ return;
+ }
+ }
+
+ dwords += count;
+ dwords_left -= count;
+ }
+
+ if (dwords_left < 0)
+ printf("**** this ain't right!! dwords_left=%d\n", dwords_left);
}
diff --git a/src/freedreno/decode/cffdec.h b/src/freedreno/decode/cffdec.h
index 695aec39de8..49b952f065f 100644
--- a/src/freedreno/decode/cffdec.h
+++ b/src/freedreno/decode/cffdec.h
@@ -27,57 +27,57 @@
#include <stdbool.h>
enum query_mode {
- /* default mode, dump all queried regs on each draw: */
- QUERY_ALL = 0,
-
- /* only dump if any of the queried regs were written
- * since last draw:
- */
- QUERY_WRITTEN,
-
- /* only dump if any of the queried regs changed since
- * last draw:
- */
- QUERY_DELTA,
+ /* default mode, dump all queried regs on each draw: */
+ QUERY_ALL = 0,
+
+ /* only dump if any of the queried regs were written
+ * since last draw:
+ */
+ QUERY_WRITTEN,
+
+ /* only dump if any of the queried regs changed since
+ * last draw:
+ */
+ QUERY_DELTA,
};
struct cffdec_options {
- unsigned gpu_id;
- int draw_filter;
- int color;
- int dump_shaders;
- int summary;
- int allregs;
- int dump_textures;
- int decode_markers;
- char *script;
-
- int query_compare; /* binning vs SYSMEM/GMEM compare mode */
- int query_mode; /* enum query_mode */
- char **querystrs;
- int nquery;
-
- /* In "once" mode, only decode a cmdstream buffer once (per draw
- * mode, in the case of a6xx+ where a single cmdstream buffer can
- * be used for both binning and draw pass), rather than each time
- * encountered (ie. once per tile/bin in GMEM draw passes)
- */
- int once;
-
- /* for crashdec, where we know CP_IBx_REM_SIZE, we can use this
- * to highlight the cmdstream not parsed yet, to make it easier
- * to see how far along the CP is.
- */
- struct {
- uint64_t base;
- uint32_t rem;
- } ibs[4];
+ unsigned gpu_id;
+ int draw_filter;
+ int color;
+ int dump_shaders;
+ int summary;
+ int allregs;
+ int dump_textures;
+ int decode_markers;
+ char *script;
+
+ int query_compare; /* binning vs SYSMEM/GMEM compare mode */
+ int query_mode; /* enum query_mode */
+ char **querystrs;
+ int nquery;
+
+ /* In "once" mode, only decode a cmdstream buffer once (per draw
+ * mode, in the case of a6xx+ where a single cmdstream buffer can
+ * be used for both binning and draw pass), rather than each time
+ * encountered (ie. once per tile/bin in GMEM draw passes)
+ */
+ int once;
+
+ /* for crashdec, where we know CP_IBx_REM_SIZE, we can use this
+ * to highlight the cmdstream not parsed yet, to make it easier
+ * to see how far along the CP is.
+ */
+ struct {
+ uint64_t base;
+ uint32_t rem;
+ } ibs[4];
};
void printl(int lvl, const char *fmt, ...);
-const char * pktname(unsigned opc);
+const char *pktname(unsigned opc);
uint32_t regbase(const char *name);
-const char * regname(uint32_t regbase, int color);
+const char *regname(uint32_t regbase, int color);
bool reg_written(uint32_t regbase);
uint32_t reg_lastval(uint32_t regbase);
uint32_t reg_val(uint32_t regbase);
@@ -91,16 +91,15 @@ void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level);
* Helpers for packet parsing:
*/
-
#define CP_TYPE0_PKT 0x00000000
#define CP_TYPE2_PKT 0x80000000
#define CP_TYPE3_PKT 0xc0000000
#define CP_TYPE4_PKT 0x40000000
#define CP_TYPE7_PKT 0x70000000
-#define pkt_is_type0(pkt) (((pkt) & 0XC0000000) == CP_TYPE0_PKT)
-#define type0_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
-#define type0_pkt_offset(pkt) ((pkt) & 0x7FFF)
+#define pkt_is_type0(pkt) (((pkt)&0XC0000000) == CP_TYPE0_PKT)
+#define type0_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
+#define type0_pkt_offset(pkt) ((pkt)&0x7FFF)
#define pkt_is_type2(pkt) ((pkt) == CP_TYPE2_PKT)
@@ -109,40 +108,37 @@ void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level);
* and 15 are 0
*/
-static inline uint pm4_calc_odd_parity_bit(uint val)
+static inline uint
+pm4_calc_odd_parity_bit(uint val)
{
- return (0x9669 >> (0xf & ((val) ^
- ((val) >> 4) ^ ((val) >> 8) ^ ((val) >> 12) ^
- ((val) >> 16) ^ ((val) >> 20) ^ ((val) >> 24) ^
- ((val) >> 28)))) & 1;
+ return (0x9669 >> (0xf & ((val) ^ ((val) >> 4) ^ ((val) >> 8) ^
+ ((val) >> 12) ^ ((val) >> 16) ^ ((val) >> 20) ^
+ ((val) >> 24) ^ ((val) >> 28)))) &
+ 1;
}
-#define pkt_is_type3(pkt) \
- ((((pkt) & 0xC0000000) == CP_TYPE3_PKT) && \
- (((pkt) & 0x80FE) == 0))
+#define pkt_is_type3(pkt) \
+ ((((pkt)&0xC0000000) == CP_TYPE3_PKT) && (((pkt)&0x80FE) == 0))
#define cp_type3_opcode(pkt) (((pkt) >> 8) & 0xFF)
-#define type3_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
+#define type3_pkt_size(pkt) ((((pkt) >> 16) & 0x3FFF) + 1)
-#define pkt_is_type4(pkt) \
- ((((pkt) & 0xF0000000) == CP_TYPE4_PKT) && \
- ((((pkt) >> 27) & 0x1) == \
- pm4_calc_odd_parity_bit(type4_pkt_offset(pkt))) \
- && ((((pkt) >> 7) & 0x1) == \
- pm4_calc_odd_parity_bit(type4_pkt_size(pkt))))
+#define pkt_is_type4(pkt) \
+ ((((pkt)&0xF0000000) == CP_TYPE4_PKT) && \
+ ((((pkt) >> 27) & 0x1) == \
+ pm4_calc_odd_parity_bit(type4_pkt_offset(pkt))) && \
+ ((((pkt) >> 7) & 0x1) == pm4_calc_odd_parity_bit(type4_pkt_size(pkt))))
#define type4_pkt_offset(pkt) (((pkt) >> 8) & 0x7FFFF)
-#define type4_pkt_size(pkt) ((pkt) & 0x7F)
+#define type4_pkt_size(pkt) ((pkt)&0x7F)
-#define pkt_is_type7(pkt) \
- ((((pkt) & 0xF0000000) == CP_TYPE7_PKT) && \
- (((pkt) & 0x0F000000) == 0) && \
- ((((pkt) >> 23) & 0x1) == \
- pm4_calc_odd_parity_bit(cp_type7_opcode(pkt))) \
- && ((((pkt) >> 15) & 0x1) == \
- pm4_calc_odd_parity_bit(type7_pkt_size(pkt))))
+#define pkt_is_type7(pkt) \
+ ((((pkt)&0xF0000000) == CP_TYPE7_PKT) && (((pkt)&0x0F000000) == 0) && \
+ ((((pkt) >> 23) & 0x1) == \
+ pm4_calc_odd_parity_bit(cp_type7_opcode(pkt))) && \
+ ((((pkt) >> 15) & 0x1) == pm4_calc_odd_parity_bit(type7_pkt_size(pkt))))
#define cp_type7_opcode(pkt) (((pkt) >> 16) & 0x7F)
-#define type7_pkt_size(pkt) ((pkt) & 0x3FFF)
+#define type7_pkt_size(pkt) ((pkt)&0x3FFF)
#endif /* __CFFDEC_H__ */
diff --git a/src/freedreno/decode/cffdump.c b/src/freedreno/decode/cffdump.c
index cd787fb43a3..098ba4b7905 100644
--- a/src/freedreno/decode/cffdump.c
+++ b/src/freedreno/decode/cffdump.c
@@ -24,33 +24,32 @@
#include <assert.h>
#include <ctype.h>
#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
-#include <fcntl.h>
-#include <string.h>
-#include <assert.h>
-#include <signal.h>
-#include <errno.h>
-#include "redump.h"
+#include "buffers.h"
+#include "cffdec.h"
#include "disasm.h"
-#include "script.h"
#include "io.h"
-#include "rnnutil.h"
#include "pager.h"
-#include "buffers.h"
-#include "cffdec.h"
+#include "redump.h"
+#include "rnnutil.h"
+#include "script.h"
static struct cffdec_options options = {
- .gpu_id = 220,
+ .gpu_id = 220,
};
static bool needs_wfi = false;
@@ -62,321 +61,331 @@ static const char *exename;
static int handle_file(const char *filename, int start, int end, int draw);
-static void print_usage(const char *name)
+static void
+print_usage(const char *name)
{
- fprintf(stderr, "Usage:\n\n"
- "\t%s [OPTSIONS]... FILE...\n\n"
- "Options:\n"
- "\t-v, --verbose - more verbose disassembly\n"
- "\t--dump-shaders - dump each shader to a raw file\n"
- "\t--no-color - disable colorized output (default for non-console\n"
- "\t output)\n"
- "\t--color - enable colorized output (default for tty output)\n"
- "\t--no-pager - disable pager (default for non-console output)\n"
- "\t--pager - enable pager (default for tty output)\n"
- "\t-s, --summary - don't show individual register writes, but just\n"
- "\t register values on draws\n"
- "\t-a, --allregs - show all registers (including ones not written\n"
- "\t since previous draw) on each draw\n"
- "\t-S, --start=N - start decoding from frame N\n"
- "\t-E, --end=N - stop decoding after frame N\n"
- "\t-F, --frame=N - decode only frame N\n"
- "\t-D, --draw=N - decode only draw N\n"
- "\t-e, --exe=NAME - only decode cmdstream from named process\n"
- "\t--textures - dump texture contents (if possible)\n"
- "\t-L, --script=LUA - run specified lua script to analyze state\n"
- "\t-q, --query=REG - query mode, dump only specified query registers on\n"
- "\t each draw; multiple --query/-q args can be given to\n"
- "\t dump multiple registers; register can be specified\n"
- "\t either by name or numeric offset\n"
- "\t--query-all - in query mode, show all queried regs on each draw\n"
- "\t (default query mode)\n"
- "\t--query-written - in query mode, show queried regs on draws if any of\n"
- "\t them have been written since previous draw\n"
- "\t--query-delta - in query mode, show queried regs on draws if any of\n"
- "\t them have changed since previous draw\n"
- "\t--query-compare - dump registers for BINNING vs GMEM/BYPASS per draw;\n"
- "\t only applicable for regs set via SDS group (a6xx+),\n"
- "\t implies --once, can be combined with --query-all,\n"
- "\t --query-written, or --query-delta\n"
- "\t--once - decode cmdstream only once (per draw mode); if same\n"
- "\t cmdstream is executed for each tile, this will decode\n"
- "\t it only for the first tile and skip the remainder,\n"
- "\t which can be useful when looking at state that does\n"
- "\t not change per tile\n"
- "\t--not-once - decode cmdstream for each IB (default)\n"
- "\t-h, --help - show this message\n"
- , name);
- exit(2);
+ /* clang-format off */
+ fprintf(stderr, "Usage:\n\n"
+ "\t%s [OPTSIONS]... FILE...\n\n"
+ "Options:\n"
+ "\t-v, --verbose - more verbose disassembly\n"
+ "\t--dump-shaders - dump each shader to a raw file\n"
+ "\t--no-color - disable colorized output (default for non-console\n"
+ "\t output)\n"
+ "\t--color - enable colorized output (default for tty output)\n"
+ "\t--no-pager - disable pager (default for non-console output)\n"
+ "\t--pager - enable pager (default for tty output)\n"
+ "\t-s, --summary - don't show individual register writes, but just\n"
+ "\t register values on draws\n"
+ "\t-a, --allregs - show all registers (including ones not written\n"
+ "\t since previous draw) on each draw\n"
+ "\t-S, --start=N - start decoding from frame N\n"
+ "\t-E, --end=N - stop decoding after frame N\n"
+ "\t-F, --frame=N - decode only frame N\n"
+ "\t-D, --draw=N - decode only draw N\n"
+ "\t-e, --exe=NAME - only decode cmdstream from named process\n"
+ "\t--textures - dump texture contents (if possible)\n"
+ "\t-L, --script=LUA - run specified lua script to analyze state\n"
+ "\t-q, --query=REG - query mode, dump only specified query registers on\n"
+ "\t each draw; multiple --query/-q args can be given to\n"
+ "\t dump multiple registers; register can be specified\n"
+ "\t either by name or numeric offset\n"
+ "\t--query-all - in query mode, show all queried regs on each draw\n"
+ "\t (default query mode)\n"
+ "\t--query-written - in query mode, show queried regs on draws if any of\n"
+ "\t them have been written since previous draw\n"
+ "\t--query-delta - in query mode, show queried regs on draws if any of\n"
+ "\t them have changed since previous draw\n"
+ "\t--query-compare - dump registers for BINNING vs GMEM/BYPASS per draw;\n"
+ "\t only applicable for regs set via SDS group (a6xx+),\n"
+ "\t implies --once, can be combined with --query-all,\n"
+ "\t --query-written, or --query-delta\n"
+ "\t--once - decode cmdstream only once (per draw mode); if same\n"
+ "\t cmdstream is executed for each tile, this will decode\n"
+ "\t it only for the first tile and skip the remainder,\n"
+ "\t which can be useful when looking at state that does\n"
+ "\t not change per tile\n"
+ "\t--not-once - decode cmdstream for each IB (default)\n"
+ "\t-h, --help - show this message\n"
+ , name);
+ /* clang-format on */
+ exit(2);
}
+/* clang-format off */
static const struct option opts[] = {
- /* Long opts that simply set a flag (no corresponding short alias: */
- { "dump-shaders", no_argument, &options.dump_shaders, 1 },
- { "no-color", no_argument, &options.color, 0 },
- { "color", no_argument, &options.color, 1 },
- { "no-pager", no_argument, &interactive, 0 },
- { "pager", no_argument, &interactive, 1 },
- { "textures", no_argument, &options.dump_textures, 1 },
- { "show-compositor", no_argument, &show_comp, 1 },
- { "query-all", no_argument, &options.query_mode, QUERY_ALL },
- { "query-written", no_argument, &options.query_mode, QUERY_WRITTEN },
- { "query-delta", no_argument, &options.query_mode, QUERY_DELTA },
- { "query-compare", no_argument, &options.query_compare, 1 },
- { "once", no_argument, &options.once, 1 },
- { "not-once", no_argument, &options.once, 0 },
-
- /* Long opts with short alias: */
- { "verbose", no_argument, 0, 'v' },
- { "summary", no_argument, 0, 's' },
- { "allregs", no_argument, 0, 'a' },
- { "start", required_argument, 0, 'S' },
- { "end", required_argument, 0, 'E' },
- { "frame", required_argument, 0, 'F' },
- { "draw", required_argument, 0, 'D' },
- { "exe", required_argument, 0, 'e' },
- { "script", required_argument, 0, 'L' },
- { "query", required_argument, 0, 'q' },
- { "help", no_argument, 0, 'h' },
+ /* Long opts that simply set a flag (no corresponding short alias: */
+ { "dump-shaders", no_argument, &options.dump_shaders, 1 },
+ { "no-color", no_argument, &options.color, 0 },
+ { "color", no_argument, &options.color, 1 },
+ { "no-pager", no_argument, &interactive, 0 },
+ { "pager", no_argument, &interactive, 1 },
+ { "textures", no_argument, &options.dump_textures, 1 },
+ { "show-compositor", no_argument, &show_comp, 1 },
+ { "query-all", no_argument, &options.query_mode, QUERY_ALL },
+ { "query-written", no_argument, &options.query_mode, QUERY_WRITTEN },
+ { "query-delta", no_argument, &options.query_mode, QUERY_DELTA },
+ { "query-compare", no_argument, &options.query_compare, 1 },
+ { "once", no_argument, &options.once, 1 },
+ { "not-once", no_argument, &options.once, 0 },
+
+ /* Long opts with short alias: */
+ { "verbose", no_argument, 0, 'v' },
+ { "summary", no_argument, 0, 's' },
+ { "allregs", no_argument, 0, 'a' },
+ { "start", required_argument, 0, 'S' },
+ { "end", required_argument, 0, 'E' },
+ { "frame", required_argument, 0, 'F' },
+ { "draw", required_argument, 0, 'D' },
+ { "exe", required_argument, 0, 'e' },
+ { "script", required_argument, 0, 'L' },
+ { "query", required_argument, 0, 'q' },
+ { "help", no_argument, 0, 'h' },
};
+/* clang-format on */
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
- enum debug_t debug = PRINT_RAW | PRINT_STATS;
- int ret = -1;
- int start = 0, end = 0x7ffffff, draw = -1;
- int c;
-
- interactive = isatty(STDOUT_FILENO);
-
- options.color = interactive;
-
- while ((c = getopt_long(argc, argv, "vsaS:E:F:D:e:L:q:h", opts, NULL)) != -1) {
- switch (c) {
- case 0:
- /* option that set a flag, nothing to do */
- break;
- case 'v':
- debug |= (PRINT_RAW | EXPAND_REPEAT | PRINT_VERBOSE);
- break;
- case 's':
- options.summary = true;
- break;
- case 'a':
- options.allregs = true;
- break;
- case 'S':
- start = atoi(optarg);
- break;
- case 'E':
- end = atoi(optarg);
- break;
- case 'F':
- start = end = atoi(optarg);
- break;
- case 'D':
- draw = atoi(optarg);
- break;
- case 'e':
- exename = optarg;
- break;
- case 'L':
- options.script = optarg;
- if (script_load(options.script)) {
- errx(-1, "error loading %s\n", options.script);
- }
- break;
- case 'q':
- options.querystrs = realloc(options.querystrs,
- (options.nquery + 1) * sizeof(*options.querystrs));
- options.querystrs[options.nquery] = optarg;
- options.nquery++;
- interactive = 0;
- break;
- case 'h':
- default:
- print_usage(argv[0]);
- }
- }
-
- disasm_a2xx_set_debug(debug);
- disasm_a3xx_set_debug(debug);
-
- if (interactive) {
- pager_open();
- }
-
- while (optind < argc) {
- ret = handle_file(argv[optind], start, end, draw);
- if (ret) {
- fprintf(stderr, "error reading: %s\n", argv[optind]);
- fprintf(stderr, "continuing..\n");
- }
- optind++;
- }
-
- if (ret)
- print_usage(argv[0]);
-
- if ((options.query_mode || options.query_compare) && !options.nquery) {
- fprintf(stderr, "query options only valid in query mode!\n");
- print_usage(argv[0]);
- }
-
- script_finish();
-
- if (interactive) {
- pager_close();
- }
-
- return ret;
+ enum debug_t debug = PRINT_RAW | PRINT_STATS;
+ int ret = -1;
+ int start = 0, end = 0x7ffffff, draw = -1;
+ int c;
+
+ interactive = isatty(STDOUT_FILENO);
+
+ options.color = interactive;
+
+ while ((c = getopt_long(argc, argv, "vsaS:E:F:D:e:L:q:h", opts, NULL)) !=
+ -1) {
+ switch (c) {
+ case 0:
+ /* option that set a flag, nothing to do */
+ break;
+ case 'v':
+ debug |= (PRINT_RAW | EXPAND_REPEAT | PRINT_VERBOSE);
+ break;
+ case 's':
+ options.summary = true;
+ break;
+ case 'a':
+ options.allregs = true;
+ break;
+ case 'S':
+ start = atoi(optarg);
+ break;
+ case 'E':
+ end = atoi(optarg);
+ break;
+ case 'F':
+ start = end = atoi(optarg);
+ break;
+ case 'D':
+ draw = atoi(optarg);
+ break;
+ case 'e':
+ exename = optarg;
+ break;
+ case 'L':
+ options.script = optarg;
+ if (script_load(options.script)) {
+ errx(-1, "error loading %s\n", options.script);
+ }
+ break;
+ case 'q':
+ options.querystrs =
+ realloc(options.querystrs,
+ (options.nquery + 1) * sizeof(*options.querystrs));
+ options.querystrs[options.nquery] = optarg;
+ options.nquery++;
+ interactive = 0;
+ break;
+ case 'h':
+ default:
+ print_usage(argv[0]);
+ }
+ }
+
+ disasm_a2xx_set_debug(debug);
+ disasm_a3xx_set_debug(debug);
+
+ if (interactive) {
+ pager_open();
+ }
+
+ while (optind < argc) {
+ ret = handle_file(argv[optind], start, end, draw);
+ if (ret) {
+ fprintf(stderr, "error reading: %s\n", argv[optind]);
+ fprintf(stderr, "continuing..\n");
+ }
+ optind++;
+ }
+
+ if (ret)
+ print_usage(argv[0]);
+
+ if ((options.query_mode || options.query_compare) && !options.nquery) {
+ fprintf(stderr, "query options only valid in query mode!\n");
+ print_usage(argv[0]);
+ }
+
+ script_finish();
+
+ if (interactive) {
+ pager_close();
+ }
+
+ return ret;
}
-static void parse_addr(uint32_t *buf, int sz, unsigned int *len, uint64_t *gpuaddr)
+static void
+parse_addr(uint32_t *buf, int sz, unsigned int *len, uint64_t *gpuaddr)
{
- *gpuaddr = buf[0];
- *len = buf[1];
- if (sz > 8)
- *gpuaddr |= ((uint64_t)(buf[2])) << 32;
+ *gpuaddr = buf[0];
+ *len = buf[1];
+ if (sz > 8)
+ *gpuaddr |= ((uint64_t)(buf[2])) << 32;
}
-static int handle_file(const char *filename, int start, int end, int draw)
+static int
+handle_file(const char *filename, int start, int end, int draw)
{
- enum rd_sect_type type = RD_NONE;
- void *buf = NULL;
- struct io *io;
- int submit = 0, got_gpu_id = 0;
- int sz, ret = 0;
- bool needs_reset = false;
- bool skip = false;
-
- options.draw_filter = draw;
-
- cffdec_init(&options);
-
- printf("Reading %s...\n", filename);
-
- script_start_cmdstream(filename);
-
- if (!strcmp(filename, "-"))
- io = io_openfd(0);
- else
- io = io_open(filename);
-
- if (!io) {
- fprintf(stderr, "could not open: %s\n", filename);
- return -1;
- }
-
- struct {
- unsigned int len;
- uint64_t gpuaddr;
- } gpuaddr = {0};
-
- while (true) {
- uint32_t arr[2];
-
- ret = io_readn(io, arr, 8);
- if (ret <= 0)
- goto end;
-
- while ((arr[0] == 0xffffffff) && (arr[1] == 0xffffffff)) {
- ret = io_readn(io, arr, 8);
- if (ret <= 0)
- goto end;
- }
-
- type = arr[0];
- sz = arr[1];
-
- if (sz < 0) {
- ret = -1;
- goto end;
- }
-
- free(buf);
-
- needs_wfi = false;
-
- buf = malloc(sz + 1);
- ((char *)buf)[sz] = '\0';
- ret = io_readn(io, buf, sz);
- if (ret < 0)
- goto end;
-
- switch(type) {
- case RD_TEST:
- printl(1, "test: %s\n", (char *)buf);
- break;
- case RD_CMD:
- is_blob = true;
- printl(2, "cmd: %s\n", (char *)buf);
- skip = false;
- if (exename) {
- skip |= (strstr(buf, exename) != buf);
- } else if (!show_comp) {
- skip |= (strstr(buf, "fdperf") == buf);
- skip |= (strstr(buf, "chrome") == buf);
- skip |= (strstr(buf, "surfaceflinger") == buf);
- skip |= ((char *)buf)[0] == 'X';
- }
- break;
- case RD_VERT_SHADER:
- printl(2, "vertex shader:\n%s\n", (char *)buf);
- break;
- case RD_FRAG_SHADER:
- printl(2, "fragment shader:\n%s\n", (char *)buf);
- break;
- case RD_GPUADDR:
- if (needs_reset) {
- reset_buffers();
- needs_reset = false;
- }
- parse_addr(buf, sz, &gpuaddr.len, &gpuaddr.gpuaddr);
- break;
- case RD_BUFFER_CONTENTS:
- add_buffer(gpuaddr.gpuaddr, gpuaddr.len, buf);
- buf = NULL;
- break;
- case RD_CMDSTREAM_ADDR:
- if ((start <= submit) && (submit <= end)) {
- unsigned int sizedwords;
- uint64_t gpuaddr;
- parse_addr(buf, sz, &sizedwords, &gpuaddr);
- printl(2, "############################################################\n");
- printl(2, "cmdstream: %d dwords\n", sizedwords);
- if (!skip) {
- script_start_submit();
- dump_commands(hostptr(gpuaddr), sizedwords, 0);
- script_end_submit();
- }
- printl(2, "############################################################\n");
- printl(2, "vertices: %d\n", vertices);
- }
- needs_reset = true;
- submit++;
- break;
- case RD_GPU_ID:
- if (!got_gpu_id) {
- options.gpu_id = *((unsigned int *)buf);
- printl(2, "gpu_id: %d\n", options.gpu_id);
- cffdec_init(&options);
- got_gpu_id = 1;
- }
- break;
- default:
- break;
- }
- }
+ enum rd_sect_type type = RD_NONE;
+ void *buf = NULL;
+ struct io *io;
+ int submit = 0, got_gpu_id = 0;
+ int sz, ret = 0;
+ bool needs_reset = false;
+ bool skip = false;
+
+ options.draw_filter = draw;
+
+ cffdec_init(&options);
+
+ printf("Reading %s...\n", filename);
+
+ script_start_cmdstream(filename);
+
+ if (!strcmp(filename, "-"))
+ io = io_openfd(0);
+ else
+ io = io_open(filename);
+
+ if (!io) {
+ fprintf(stderr, "could not open: %s\n", filename);
+ return -1;
+ }
+
+ struct {
+ unsigned int len;
+ uint64_t gpuaddr;
+ } gpuaddr = {0};
+
+ while (true) {
+ uint32_t arr[2];
+
+ ret = io_readn(io, arr, 8);
+ if (ret <= 0)
+ goto end;
+
+ while ((arr[0] == 0xffffffff) && (arr[1] == 0xffffffff)) {
+ ret = io_readn(io, arr, 8);
+ if (ret <= 0)
+ goto end;
+ }
+
+ type = arr[0];
+ sz = arr[1];
+
+ if (sz < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ free(buf);
+
+ needs_wfi = false;
+
+ buf = malloc(sz + 1);
+ ((char *)buf)[sz] = '\0';
+ ret = io_readn(io, buf, sz);
+ if (ret < 0)
+ goto end;
+
+ switch (type) {
+ case RD_TEST:
+ printl(1, "test: %s\n", (char *)buf);
+ break;
+ case RD_CMD:
+ is_blob = true;
+ printl(2, "cmd: %s\n", (char *)buf);
+ skip = false;
+ if (exename) {
+ skip |= (strstr(buf, exename) != buf);
+ } else if (!show_comp) {
+ skip |= (strstr(buf, "fdperf") == buf);
+ skip |= (strstr(buf, "chrome") == buf);
+ skip |= (strstr(buf, "surfaceflinger") == buf);
+ skip |= ((char *)buf)[0] == 'X';
+ }
+ break;
+ case RD_VERT_SHADER:
+ printl(2, "vertex shader:\n%s\n", (char *)buf);
+ break;
+ case RD_FRAG_SHADER:
+ printl(2, "fragment shader:\n%s\n", (char *)buf);
+ break;
+ case RD_GPUADDR:
+ if (needs_reset) {
+ reset_buffers();
+ needs_reset = false;
+ }
+ parse_addr(buf, sz, &gpuaddr.len, &gpuaddr.gpuaddr);
+ break;
+ case RD_BUFFER_CONTENTS:
+ add_buffer(gpuaddr.gpuaddr, gpuaddr.len, buf);
+ buf = NULL;
+ break;
+ case RD_CMDSTREAM_ADDR:
+ if ((start <= submit) && (submit <= end)) {
+ unsigned int sizedwords;
+ uint64_t gpuaddr;
+ parse_addr(buf, sz, &sizedwords, &gpuaddr);
+ printl(2, "############################################################\n");
+ printl(2, "cmdstream: %d dwords\n", sizedwords);
+ if (!skip) {
+ script_start_submit();
+ dump_commands(hostptr(gpuaddr), sizedwords, 0);
+ script_end_submit();
+ }
+ printl(2, "############################################################\n");
+ printl(2, "vertices: %d\n", vertices);
+ }
+ needs_reset = true;
+ submit++;
+ break;
+ case RD_GPU_ID:
+ if (!got_gpu_id) {
+ options.gpu_id = *((unsigned int *)buf);
+ printl(2, "gpu_id: %d\n", options.gpu_id);
+ cffdec_init(&options);
+ got_gpu_id = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
end:
- script_end_cmdstream();
+ script_end_cmdstream();
- io_close(io);
- fflush(stdout);
+ io_close(io);
+ fflush(stdout);
- if (ret < 0) {
- printf("corrupt file\n");
- }
- return 0;
+ if (ret < 0) {
+ printf("corrupt file\n");
+ }
+ return 0;
}
diff --git a/src/freedreno/decode/crashdec.c b/src/freedreno/decode/crashdec.c
index fcb4c154191..cb6ff79e207 100644
--- a/src/freedreno/decode/crashdec.c
+++ b/src/freedreno/decode/crashdec.c
@@ -36,7 +36,6 @@
* or times out after 5min)
*/
-
#include <assert.h>
#include <getopt.h>
#include <inttypes.h>
@@ -48,14 +47,13 @@
#include <string.h>
#include <unistd.h>
+#include "ir3/instr-a3xx.h"
#include "buffers.h"
#include "cffdec.h"
#include "disasm.h"
#include "pager.h"
#include "rnnutil.h"
#include "util.h"
-#include "ir3/instr-a3xx.h"
-
static FILE *in;
static bool verbose;
@@ -65,12 +63,24 @@ static struct rnn *rnn_control;
static struct rnn *rnn_pipe;
static struct cffdec_options options = {
- .draw_filter = -1,
+ .draw_filter = -1,
};
-static inline bool is_a6xx(void) { return (600 <= options.gpu_id) && (options.gpu_id < 700); }
-static inline bool is_a5xx(void) { return (500 <= options.gpu_id) && (options.gpu_id < 600); }
-static inline bool is_64b(void) { return options.gpu_id >= 500; }
+static inline bool
+is_a6xx(void)
+{
+ return (600 <= options.gpu_id) && (options.gpu_id < 700);
+}
+static inline bool
+is_a5xx(void)
+{
+ return (500 <= options.gpu_id) && (options.gpu_id < 600);
+}
+static inline bool
+is_64b(void)
+{
+ return options.gpu_id >= 500;
+}
/*
* Helpers to read register values:
@@ -80,20 +90,20 @@ static inline bool is_64b(void) { return options.gpu_id >= 500; }
static uint64_t
regval64(const char *name)
{
- unsigned reg = regbase(name);
- assert(reg);
- uint64_t val = reg_val(reg);
- if (is_64b())
- val |= ((uint64_t)reg_val(reg + 1)) << 32;
- return val;
+ unsigned reg = regbase(name);
+ assert(reg);
+ uint64_t val = reg_val(reg);
+ if (is_64b())
+ val |= ((uint64_t)reg_val(reg + 1)) << 32;
+ return val;
}
static uint32_t
regval(const char *name)
{
- unsigned reg = regbase(name);
- assert(reg);
- return reg_val(reg);
+ unsigned reg = regbase(name);
+ assert(reg);
+ return reg_val(reg);
}
/*
@@ -103,18 +113,18 @@ regval(const char *name)
static char *
replacestr(char *line, const char *find, const char *replace)
{
- char *tail, *s;
+ char *tail, *s;
- if (!(s = strstr(line, find)))
- return line;
+ if (!(s = strstr(line, find)))
+ return line;
- tail = s + strlen(find);
+ tail = s + strlen(find);
- char *newline;
- asprintf(&newline, "%.*s%s%s", (int)(s - line), line, replace, tail);
- free(line);
+ char *newline;
+ asprintf(&newline, "%.*s%s%s", (int)(s - line), line, replace, tail);
+ free(line);
- return newline;
+ return newline;
}
static char *lastline;
@@ -123,246 +133,247 @@ static char *pushedline;
static const char *
popline(void)
{
- char *r = pushedline;
+ char *r = pushedline;
- if (r) {
- pushedline = NULL;
- return r;
- }
+ if (r) {
+ pushedline = NULL;
+ return r;
+ }
- free(lastline);
+ free(lastline);
- size_t n = 0;
- if (getline(&r, &n, in) < 0)
- exit(0);
+ size_t n = 0;
+ if (getline(&r, &n, in) < 0)
+ exit(0);
- /* Handle section name typo's from earlier kernels: */
- r = replacestr(r, "CP_MEMPOOOL", "CP_MEMPOOL");
- r = replacestr(r, "CP_SEQ_STAT", "CP_SQE_STAT");
+ /* Handle section name typo's from earlier kernels: */
+ r = replacestr(r, "CP_MEMPOOOL", "CP_MEMPOOL");
+ r = replacestr(r, "CP_SEQ_STAT", "CP_SQE_STAT");
- lastline = r;
- return r;
+ lastline = r;
+ return r;
}
static void
pushline(void)
{
- assert(!pushedline);
- pushedline = lastline;
+ assert(!pushedline);
+ pushedline = lastline;
}
static uint32_t *
popline_ascii85(uint32_t sizedwords)
{
- const char *line = popline();
-
- /* At this point we exepct the ascii85 data to be indented *some*
- * amount, and to terminate at the end of the line. So just eat
- * up the leading whitespace.
- */
- assert(*line == ' ');
- while (*line == ' ')
- line++;
-
- uint32_t *buf = calloc(1, 4 * sizedwords);
- int idx = 0;
-
- while (*line != '\n') {
- if (*line == 'z') {
- buf[idx++] = 0;
- line++;
- continue;
- }
-
- uint32_t accum = 0;
- for (int i = 0; (i < 5) && (*line != '\n'); i++) {
- accum *= 85;
- accum += *line - '!';
- line++;
- }
-
- buf[idx++] = accum;
- }
-
- return buf;
+ const char *line = popline();
+
+ /* At this point we exepct the ascii85 data to be indented *some*
+ * amount, and to terminate at the end of the line. So just eat
+ * up the leading whitespace.
+ */
+ assert(*line == ' ');
+ while (*line == ' ')
+ line++;
+
+ uint32_t *buf = calloc(1, 4 * sizedwords);
+ int idx = 0;
+
+ while (*line != '\n') {
+ if (*line == 'z') {
+ buf[idx++] = 0;
+ line++;
+ continue;
+ }
+
+ uint32_t accum = 0;
+ for (int i = 0; (i < 5) && (*line != '\n'); i++) {
+ accum *= 85;
+ accum += *line - '!';
+ line++;
+ }
+
+ buf[idx++] = accum;
+ }
+
+ return buf;
}
static bool
startswith(const char *line, const char *start)
{
- return strstr(line, start) == line;
+ return strstr(line, start) == line;
}
static void
parseline(const char *line, const char *fmt, ...)
{
- int fmtlen = strlen(fmt);
- int n = 0;
- int l = 0;
-
- /* scan fmt string to extract expected # of conversions: */
- for (int i = 0; i < fmtlen; i++) {
- if (fmt[i] == '%') {
- if (i == (l - 1)) { /* prev char was %, ie. we have %% */
- n--;
- l = 0;
- } else {
- n++;
- l = i;
- }
- }
- }
-
- va_list ap;
- va_start(ap, fmt);
- if (vsscanf(line, fmt, ap) != n) {
- fprintf(stderr, "parse error scanning: '%s'\n", fmt);
- exit(1);
- }
- va_end(ap);
+ int fmtlen = strlen(fmt);
+ int n = 0;
+ int l = 0;
+
+ /* scan fmt string to extract expected # of conversions: */
+ for (int i = 0; i < fmtlen; i++) {
+ if (fmt[i] == '%') {
+ if (i == (l - 1)) { /* prev char was %, ie. we have %% */
+ n--;
+ l = 0;
+ } else {
+ n++;
+ l = i;
+ }
+ }
+ }
+
+ va_list ap;
+ va_start(ap, fmt);
+ if (vsscanf(line, fmt, ap) != n) {
+ fprintf(stderr, "parse error scanning: '%s'\n", fmt);
+ exit(1);
+ }
+ va_end(ap);
}
-#define foreach_line_in_section(_line) \
- for (const char *_line = popline(); _line; _line = popline()) \
- /* check for start of next section */ \
- if (_line[0] != ' ') { \
- pushline(); \
- break; \
- } else
+#define foreach_line_in_section(_line) \
+ for (const char *_line = popline(); _line; _line = popline()) \
+ /* check for start of next section */ \
+ if (_line[0] != ' ') { \
+ pushline(); \
+ break; \
+ } else
/*
* Decode ringbuffer section:
*/
static struct {
- uint64_t iova;
- uint32_t rptr;
- uint32_t wptr;
- uint32_t size;
- uint32_t *buf;
+ uint64_t iova;
+ uint32_t rptr;
+ uint32_t wptr;
+ uint32_t size;
+ uint32_t *buf;
} ringbuffers[5];
static void
decode_ringbuffer(void)
{
- int id = 0;
-
- foreach_line_in_section (line) {
- if (startswith(line, " - id:")) {
- parseline(line, " - id: %d", &id);
- assert(id < ARRAY_SIZE(ringbuffers));
- } else if (startswith(line, " iova:")) {
- parseline(line, " iova: %"PRIx64, &ringbuffers[id].iova);
- } else if (startswith(line, " rptr:")) {
- parseline(line, " rptr: %d", &ringbuffers[id].rptr);
- } else if (startswith(line, " wptr:")) {
- parseline(line, " wptr: %d", &ringbuffers[id].wptr);
- } else if (startswith(line, " size:")) {
- parseline(line, " size: %d", &ringbuffers[id].size);
- } else if (startswith(line, " data: !!ascii85 |")) {
- ringbuffers[id].buf = popline_ascii85(ringbuffers[id].size / 4);
- add_buffer(ringbuffers[id].iova, ringbuffers[id].size, ringbuffers[id].buf);
- continue;
- }
-
- printf("%s", line);
- }
+ int id = 0;
+
+ foreach_line_in_section (line) {
+ if (startswith(line, " - id:")) {
+ parseline(line, " - id: %d", &id);
+ assert(id < ARRAY_SIZE(ringbuffers));
+ } else if (startswith(line, " iova:")) {
+ parseline(line, " iova: %" PRIx64, &ringbuffers[id].iova);
+ } else if (startswith(line, " rptr:")) {
+ parseline(line, " rptr: %d", &ringbuffers[id].rptr);
+ } else if (startswith(line, " wptr:")) {
+ parseline(line, " wptr: %d", &ringbuffers[id].wptr);
+ } else if (startswith(line, " size:")) {
+ parseline(line, " size: %d", &ringbuffers[id].size);
+ } else if (startswith(line, " data: !!ascii85 |")) {
+ ringbuffers[id].buf = popline_ascii85(ringbuffers[id].size / 4);
+ add_buffer(ringbuffers[id].iova, ringbuffers[id].size,
+ ringbuffers[id].buf);
+ continue;
+ }
+
+ printf("%s", line);
+ }
}
static bool
valid_header(uint32_t pkt)
{
- if (options.gpu_id >= 500) {
- return pkt_is_type4(pkt) || pkt_is_type7(pkt);
- } else {
- /* TODO maybe we can check validish looking pkt3 opc or pkt0
- * register offset.. the cmds sent by kernel are usually
- * fairly limited (other than initialization) which confines
- * the search space a bit..
- */
- return true;
- }
+ if (options.gpu_id >= 500) {
+ return pkt_is_type4(pkt) || pkt_is_type7(pkt);
+ } else {
+ /* TODO maybe we can check validish looking pkt3 opc or pkt0
+ * register offset.. the cmds sent by kernel are usually
+ * fairly limited (other than initialization) which confines
+ * the search space a bit..
+ */
+ return true;
+ }
}
static void
dump_cmdstream(void)
{
- uint64_t rb_base = regval64("CP_RB_BASE");
-
- printf("got rb_base=%"PRIx64"\n", rb_base);
-
- options.ibs[1].base = regval64("CP_IB1_BASE");
- options.ibs[1].rem = regval("CP_IB1_REM_SIZE");
- options.ibs[2].base = regval64("CP_IB2_BASE");
- options.ibs[2].rem = regval("CP_IB2_REM_SIZE");
-
- /* Adjust remaining size to account for cmdstream slurped into ROQ
- * but not yet consumed by SQE
- *
- * TODO add support for earlier GPUs once we tease out the needed
- * registers.. see crashit.c in msmtest for hints.
- *
- * TODO it would be nice to be able to extract out register bitfields
- * by name rather than hard-coding this.
- */
- if (is_a6xx()) {
- options.ibs[1].rem += regval("CP_CSQ_IB1_STAT") >> 16;
- options.ibs[2].rem += regval("CP_CSQ_IB2_STAT") >> 16;
- }
-
- printf("IB1: %"PRIx64", %u\n", options.ibs[1].base, options.ibs[1].rem);
- printf("IB2: %"PRIx64", %u\n", options.ibs[2].base, options.ibs[2].rem);
-
- /* now that we've got the regvals we want, reset register state
- * so we aren't seeing values from decode_registers();
- */
- reset_regs();
-
- for (int id = 0; id < ARRAY_SIZE(ringbuffers); id++) {
- if (ringbuffers[id].iova != rb_base)
- continue;
- if (!ringbuffers[id].size)
- continue;
-
- printf("found ring!\n");
-
- /* The kernel level ringbuffer (RB) wraps around, which
- * cffdec doesn't really deal with.. so figure out how
- * many dwords are unread
- */
- unsigned ringszdw = ringbuffers[id].size >> 2; /* in dwords */
+ uint64_t rb_base = regval64("CP_RB_BASE");
+
+ printf("got rb_base=%" PRIx64 "\n", rb_base);
+
+ options.ibs[1].base = regval64("CP_IB1_BASE");
+ options.ibs[1].rem = regval("CP_IB1_REM_SIZE");
+ options.ibs[2].base = regval64("CP_IB2_BASE");
+ options.ibs[2].rem = regval("CP_IB2_REM_SIZE");
+
+ /* Adjust remaining size to account for cmdstream slurped into ROQ
+ * but not yet consumed by SQE
+ *
+ * TODO add support for earlier GPUs once we tease out the needed
+ * registers.. see crashit.c in msmtest for hints.
+ *
+ * TODO it would be nice to be able to extract out register bitfields
+ * by name rather than hard-coding this.
+ */
+ if (is_a6xx()) {
+ options.ibs[1].rem += regval("CP_CSQ_IB1_STAT") >> 16;
+ options.ibs[2].rem += regval("CP_CSQ_IB2_STAT") >> 16;
+ }
+
+ printf("IB1: %" PRIx64 ", %u\n", options.ibs[1].base, options.ibs[1].rem);
+ printf("IB2: %" PRIx64 ", %u\n", options.ibs[2].base, options.ibs[2].rem);
+
+ /* now that we've got the regvals we want, reset register state
+ * so we aren't seeing values from decode_registers();
+ */
+ reset_regs();
+
+ for (int id = 0; id < ARRAY_SIZE(ringbuffers); id++) {
+ if (ringbuffers[id].iova != rb_base)
+ continue;
+ if (!ringbuffers[id].size)
+ continue;
+
+ printf("found ring!\n");
+
+ /* The kernel level ringbuffer (RB) wraps around, which
+ * cffdec doesn't really deal with.. so figure out how
+ * many dwords are unread
+ */
+ unsigned ringszdw = ringbuffers[id].size >> 2; /* in dwords */
/* helper macro to deal with modulo size math: */
-#define mod_add(b, v) ((ringszdw + (int)(b) + (int)(v)) % ringszdw)
-
- /* The rptr will (most likely) have moved past the IB to
- * userspace cmdstream, so back up a bit, and then advance
- * until we find a valid start of a packet.. this is going
- * to be less reliable on a4xx and before (pkt0/pkt3),
- * compared to pkt4/pkt7 with parity bits
- */
- const int lookback = 12;
- unsigned rptr = mod_add(ringbuffers[id].rptr, -lookback);
-
- for (int idx = 0; idx < lookback; idx++) {
- if (valid_header(ringbuffers[id].buf[rptr]))
- break;
- rptr = mod_add(rptr, 1);
- }
-
- unsigned cmdszdw = mod_add(ringbuffers[id].wptr, -rptr);
-
- printf("got cmdszdw=%d\n", cmdszdw);
- uint32_t *buf = malloc(cmdszdw * 4);
-
- for (int idx = 0; idx < cmdszdw; idx++) {
- int p = mod_add(rptr, idx);
- buf[idx] = ringbuffers[id].buf[p];
- }
-
- dump_commands(buf, cmdszdw, 0);
- free(buf);
- }
+#define mod_add(b, v) ((ringszdw + (int)(b) + (int)(v)) % ringszdw)
+
+ /* The rptr will (most likely) have moved past the IB to
+ * userspace cmdstream, so back up a bit, and then advance
+ * until we find a valid start of a packet.. this is going
+ * to be less reliable on a4xx and before (pkt0/pkt3),
+ * compared to pkt4/pkt7 with parity bits
+ */
+ const int lookback = 12;
+ unsigned rptr = mod_add(ringbuffers[id].rptr, -lookback);
+
+ for (int idx = 0; idx < lookback; idx++) {
+ if (valid_header(ringbuffers[id].buf[rptr]))
+ break;
+ rptr = mod_add(rptr, 1);
+ }
+
+ unsigned cmdszdw = mod_add(ringbuffers[id].wptr, -rptr);
+
+ printf("got cmdszdw=%d\n", cmdszdw);
+ uint32_t *buf = malloc(cmdszdw * 4);
+
+ for (int idx = 0; idx < cmdszdw; idx++) {
+ int p = mod_add(rptr, idx);
+ buf[idx] = ringbuffers[id].buf[p];
+ }
+
+ dump_commands(buf, cmdszdw, 0);
+ free(buf);
+ }
}
/*
@@ -372,27 +383,27 @@ dump_cmdstream(void)
static void
decode_bos(void)
{
- uint32_t size = 0;
- uint64_t iova = 0;
+ uint32_t size = 0;
+ uint64_t iova = 0;
- foreach_line_in_section (line) {
- if (startswith(line, " - iova:")) {
- parseline(line, " - iova: %"PRIx64, &iova);
- } else if (startswith(line, " size:")) {
- parseline(line, " size: %u", &size);
- } else if (startswith(line, " data: !!ascii85 |")) {
- uint32_t *buf = popline_ascii85(size / 4);
+ foreach_line_in_section (line) {
+ if (startswith(line, " - iova:")) {
+ parseline(line, " - iova: %" PRIx64, &iova);
+ } else if (startswith(line, " size:")) {
+ parseline(line, " size: %u", &size);
+ } else if (startswith(line, " data: !!ascii85 |")) {
+ uint32_t *buf = popline_ascii85(size / 4);
- if (verbose)
- dump_hex_ascii(buf, size, 1);
+ if (verbose)
+ dump_hex_ascii(buf, size, 1);
- add_buffer(iova, size, buf);
+ add_buffer(iova, size, buf);
- continue;
- }
+ continue;
+ }
- printf("%s", line);
- }
+ printf("%s", line);
+ }
}
/*
@@ -402,59 +413,59 @@ decode_bos(void)
static void
dump_register(struct rnn *rnn, uint32_t offset, uint32_t value)
{
- struct rnndecaddrinfo *info = rnn_reginfo(rnn, offset);
- if (info && info->typeinfo) {
- char *decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value);
- printf("%s: %s\n", info->name, decoded);
- } else if (info) {
- printf("%s: %08x\n", info->name, value);
- } else {
- printf("<%04x>: %08x\n", offset, value);
- }
+ struct rnndecaddrinfo *info = rnn_reginfo(rnn, offset);
+ if (info && info->typeinfo) {
+ char *decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value);
+ printf("%s: %s\n", info->name, decoded);
+ } else if (info) {
+ printf("%s: %08x\n", info->name, value);
+ } else {
+ printf("<%04x>: %08x\n", offset, value);
+ }
}
static void
decode_gmu_registers(void)
{
- foreach_line_in_section (line) {
- uint32_t offset, value;
- parseline(line, " - { offset: %x, value: %x }", &offset, &value);
+ foreach_line_in_section (line) {
+ uint32_t offset, value;
+ parseline(line, " - { offset: %x, value: %x }", &offset, &value);
- printf("\t%08x\t", value);
- dump_register(rnn_gmu, offset/4, value);
- }
+ printf("\t%08x\t", value);
+ dump_register(rnn_gmu, offset / 4, value);
+ }
}
static void
decode_registers(void)
{
- foreach_line_in_section (line) {
- uint32_t offset, value;
- parseline(line, " - { offset: %x, value: %x }", &offset, &value);
-
- reg_set(offset/4, value);
- printf("\t%08x", value);
- dump_register_val(offset/4, value, 0);
- }
+ foreach_line_in_section (line) {
+ uint32_t offset, value;
+ parseline(line, " - { offset: %x, value: %x }", &offset, &value);
+
+ reg_set(offset / 4, value);
+ printf("\t%08x", value);
+ dump_register_val(offset / 4, value, 0);
+ }
}
/* similar to registers section, but for banked context regs: */
static void
decode_clusters(void)
{
- foreach_line_in_section (line) {
- if (startswith(line, " - cluster-name:") ||
- startswith(line, " - context:")) {
- printf("%s", line);
- continue;
- }
-
- uint32_t offset, value;
- parseline(line, " - { offset: %x, value: %x }", &offset, &value);
-
- printf("\t%08x", value);
- dump_register_val(offset/4, value, 0);
- }
+ foreach_line_in_section (line) {
+ if (startswith(line, " - cluster-name:") ||
+ startswith(line, " - context:")) {
+ printf("%s", line);
+ continue;
+ }
+
+ uint32_t offset, value;
+ parseline(line, " - { offset: %x, value: %x }", &offset, &value);
+
+ printf("\t%08x", value);
+ dump_register_val(offset / 4, value, 0);
+ }
}
/*
@@ -465,407 +476,413 @@ decode_clusters(void)
static void
dump_cp_sqe_stat(uint32_t *stat)
{
- printf("\t PC: %04x\n", stat[0]);
- stat++;
-
- if (is_a6xx() && valid_header(stat[0])) {
- if (pkt_is_type7(stat[0])) {
- unsigned opc = cp_type7_opcode(stat[0]);
- const char *name = pktname(opc);
- if (name)
- printf("\tPKT: %s\n", name);
- } else {
- /* Not sure if this case can happen: */
- }
- }
-
- for (int i = 0; i < 16; i++) {
- printf("\t$%02x: %08x\t\t$%02x: %08x\n",
- i + 1, stat[i], i + 16 + 1, stat[i + 16]);
- }
+ printf("\t PC: %04x\n", stat[0]);
+ stat++;
+
+ if (is_a6xx() && valid_header(stat[0])) {
+ if (pkt_is_type7(stat[0])) {
+ unsigned opc = cp_type7_opcode(stat[0]);
+ const char *name = pktname(opc);
+ if (name)
+ printf("\tPKT: %s\n", name);
+ } else {
+ /* Not sure if this case can happen: */
+ }
+ }
+
+ for (int i = 0; i < 16; i++) {
+ printf("\t$%02x: %08x\t\t$%02x: %08x\n", i + 1, stat[i], i + 16 + 1,
+ stat[i + 16]);
+ }
}
static void
dump_control_regs(uint32_t *regs)
{
- if (!rnn_control)
- return;
-
- /* Control regs 0x100-0x17f are a scratch space to be used by the
- * firmware however it wants, unlike lower regs which involve some
- * fixed-function units. Therefore only these registers get dumped
- * directly.
- */
- for (uint32_t i = 0; i < 0x80; i++) {
- printf("\t%08x\t", regs[i]);
- dump_register(rnn_control, i + 0x100, regs[i]);
- }
+ if (!rnn_control)
+ return;
+
+ /* Control regs 0x100-0x17f are a scratch space to be used by the
+ * firmware however it wants, unlike lower regs which involve some
+ * fixed-function units. Therefore only these registers get dumped
+ * directly.
+ */
+ for (uint32_t i = 0; i < 0x80; i++) {
+ printf("\t%08x\t", regs[i]);
+ dump_register(rnn_control, i + 0x100, regs[i]);
+ }
}
static void
dump_cp_ucode_dbg(uint32_t *dbg)
{
- /* Notes on the data:
- * There seems to be a section every 4096 DWORD's. The sections aren't
- * all the same size, so the rest of the 4096 DWORD's are filled with
- * mirrors of the actual data.
- */
-
- for (int section = 0; section < 6; section++, dbg += 0x1000) {
- switch (section) {
- case 0:
- /* Contains scattered data from a630_sqe.fw: */
- printf("\tSQE instruction cache:\n");
- dump_hex_ascii(dbg, 4 * 0x400, 1);
- break;
- case 1:
- printf("\tUnknown 1:\n");
- dump_hex_ascii(dbg, 4 * 0x80, 1);
- break;
- case 2:
- printf("\tUnknown 2:\n");
- dump_hex_ascii(dbg, 4 * 0x200, 1);
- break;
- case 3:
- printf("\tUnknown 3:\n");
- dump_hex_ascii(dbg, 4 * 0x80, 1);
- break;
- case 4:
- /* Don't bother printing this normally */
- if (verbose) {
- printf("\tSQE packet jumptable contents:\n");
- dump_hex_ascii(dbg, 4 * 0x80, 1);
- }
- break;
- case 5:
- printf("\tSQE scratch control regs:\n");
- dump_control_regs(dbg);
- break;
- }
- }
+ /* Notes on the data:
+ * There seems to be a section every 4096 DWORD's. The sections aren't
+ * all the same size, so the rest of the 4096 DWORD's are filled with
+ * mirrors of the actual data.
+ */
+
+ for (int section = 0; section < 6; section++, dbg += 0x1000) {
+ switch (section) {
+ case 0:
+ /* Contains scattered data from a630_sqe.fw: */
+ printf("\tSQE instruction cache:\n");
+ dump_hex_ascii(dbg, 4 * 0x400, 1);
+ break;
+ case 1:
+ printf("\tUnknown 1:\n");
+ dump_hex_ascii(dbg, 4 * 0x80, 1);
+ break;
+ case 2:
+ printf("\tUnknown 2:\n");
+ dump_hex_ascii(dbg, 4 * 0x200, 1);
+ break;
+ case 3:
+ printf("\tUnknown 3:\n");
+ dump_hex_ascii(dbg, 4 * 0x80, 1);
+ break;
+ case 4:
+ /* Don't bother printing this normally */
+ if (verbose) {
+ printf("\tSQE packet jumptable contents:\n");
+ dump_hex_ascii(dbg, 4 * 0x80, 1);
+ }
+ break;
+ case 5:
+ printf("\tSQE scratch control regs:\n");
+ dump_control_regs(dbg);
+ break;
+ }
+ }
}
static void
-dump_mem_pool_reg_write(unsigned reg, uint32_t data, unsigned context, bool pipe)
+dump_mem_pool_reg_write(unsigned reg, uint32_t data, unsigned context,
+ bool pipe)
{
- if (pipe) {
- struct rnndecaddrinfo *info = rnn_reginfo(rnn_pipe, reg);
- printf("\t\twrite %s (%02x) pipe\n", info->name, reg);
-
- if (!strcmp(info->typeinfo->name, "void")) {
- /* registers that ignore their payload */
- } else {
- printf("\t\t\t");
- dump_register(rnn_pipe, reg, data);
- }
- } else {
- printf("\t\twrite %s (%05x) context %d\n", regname(reg, 1), reg, context);
- dump_register_val(reg, data, 2);
- }
+ if (pipe) {
+ struct rnndecaddrinfo *info = rnn_reginfo(rnn_pipe, reg);
+ printf("\t\twrite %s (%02x) pipe\n", info->name, reg);
+
+ if (!strcmp(info->typeinfo->name, "void")) {
+ /* registers that ignore their payload */
+ } else {
+ printf("\t\t\t");
+ dump_register(rnn_pipe, reg, data);
+ }
+ } else {
+ printf("\t\twrite %s (%05x) context %d\n", regname(reg, 1), reg, context);
+ dump_register_val(reg, data, 2);
+ }
}
static void
dump_mem_pool_chunk(const uint32_t *chunk)
{
- struct __attribute__((packed)) {
- bool reg0_enabled : 1;
- bool reg1_enabled : 1;
- uint32_t data0 : 32;
- uint32_t data1 : 32;
- uint32_t reg0 : 18;
- uint32_t reg1 : 18;
- bool reg0_pipe : 1;
- bool reg1_pipe : 1;
- uint32_t reg0_context : 1;
- uint32_t reg1_context : 1;
- uint32_t padding : 22;
- } fields;
-
- memcpy(&fields, chunk, 4 * sizeof(uint32_t));
-
- if (fields.reg0_enabled) {
- dump_mem_pool_reg_write(fields.reg0, fields.data0, fields.reg0_context, fields.reg0_pipe);
- }
-
- if (fields.reg1_enabled) {
- dump_mem_pool_reg_write(fields.reg1, fields.data1, fields.reg1_context, fields.reg1_pipe);
- }
+ struct __attribute__((packed)) {
+ bool reg0_enabled : 1;
+ bool reg1_enabled : 1;
+ uint32_t data0 : 32;
+ uint32_t data1 : 32;
+ uint32_t reg0 : 18;
+ uint32_t reg1 : 18;
+ bool reg0_pipe : 1;
+ bool reg1_pipe : 1;
+ uint32_t reg0_context : 1;
+ uint32_t reg1_context : 1;
+ uint32_t padding : 22;
+ } fields;
+
+ memcpy(&fields, chunk, 4 * sizeof(uint32_t));
+
+ if (fields.reg0_enabled) {
+ dump_mem_pool_reg_write(fields.reg0, fields.data0, fields.reg0_context,
+ fields.reg0_pipe);
+ }
+
+ if (fields.reg1_enabled) {
+ dump_mem_pool_reg_write(fields.reg1, fields.data1, fields.reg1_context,
+ fields.reg1_pipe);
+ }
}
static void
dump_cp_mem_pool(uint32_t *mempool)
{
- /* The mem pool is a shared pool of memory used for storing in-flight
- * register writes. There are 6 different queues, one for each
- * cluster. Writing to $data (or for some special registers, $addr)
- * pushes data onto the appropriate queue, and each queue is pulled
- * from by the appropriate cluster. The queues are thus written to
- * in-order, but may be read out-of-order.
- *
- * The queues are conceptually divided into 128-bit "chunks", and the
- * read and write pointers are in units of chunks. These chunks are
- * organized internally into 8-chunk "blocks", and memory is allocated
- * dynamically in terms of blocks. Each queue is represented as a
- * singly-linked list of blocks, as well as 3-bit start/end chunk
- * pointers that point within the first/last block. The next pointers
- * are located in a separate array, rather than inline.
- */
-
- /* TODO: The firmware CP_MEM_POOL save/restore routines do something
- * like:
- *
- * cread $02, [ $00 + 0 ]
- * and $02, $02, 0x118
- * ...
- * brne $02, 0, #label
- * mov $03, 0x2000
- * mov $03, 0x1000
- * label:
- * ...
- *
- * I think that control register 0 is the GPU version, and some
- * versions have a smaller mem pool. It seems some models have a mem
- * pool that's half the size, and a bunch of offsets are shifted
- * accordingly. Unfortunately the kernel driver's dumping code doesn't
- * seem to take this into account, even the downstream android driver,
- * and we don't know which versions 0x8, 0x10, or 0x100 correspond
- * to. Or maybe we can use CP_DBG_MEM_POOL_SIZE to figure this out?
- */
- bool small_mem_pool = false;
-
- /* The array of next pointers for each block. */
- const uint32_t *next_pointers = small_mem_pool ? &mempool[0x800] : &mempool[0x1000];
-
- /* Maximum number of blocks in the pool, also the size of the pointers
- * array.
- */
- const int num_blocks = small_mem_pool ? 0x30 : 0x80;
-
- /* Number of queues */
- const unsigned num_queues = 6;
-
- /* Unfortunately the per-queue state is a little more complicated than
- * a simple pair of begin/end pointers. Instead of a single beginning
- * block, there are *two*, with the property that either the two are
- * equal or the second is the "next" of the first. Similarly there are
- * two end blocks. Thus the queue either looks like this:
- *
- * A -> B -> ... -> C -> D
- *
- * Or like this, or some combination:
- *
- * A/B -> ... -> C/D
- *
- * However, there's only one beginning/end chunk offset. Now the
- * question is, which of A or B is the actual start? I.e. is the chunk
- * offset an offset inside A or B? It depends. I'll show a typical read
- * cycle, starting here (read pointer marked with a *) with a chunk
- * offset of 0:
- *
- * A B
- * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- * |_|_|_|_|_|_|_|_| -> |*|_|_|_|_|_|_|_| -> |_|_|_|_|_|_|_|_|
- *
- * Once the pointer advances far enough, the hardware decides to free
- * A, after which the read-side state looks like:
- *
- * (free) A/B
- * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- * |_|_|_|_|_|_|_|_| |_|_|_|*|_|_|_|_| -> |_|_|_|_|_|_|_|_|
- *
- * Then after advancing the pointer a bit more, the hardware fetches
- * the "next" pointer for A and stores it in B:
- *
- * (free) A B
- * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- * |_|_|_|_|_|_|_|_| |_|_|_|_|_|_|_|*| -> |_|_|_|_|_|_|_|_|
- *
- * Then the read pointer advances into B, at which point we've come
- * back to the first state having advanced a whole block:
- *
- * (free) A B
- * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- * |_|_|_|_|_|_|_|_| |_|_|_|_|_|_|_|_| -> |*|_|_|_|_|_|_|_|
- *
- *
- * There is a similar cycle for the write pointer. Now, the question
- * is, how do we know which state we're in? We need to know this to
- * know whether the pointer (*) is in A or B if they're different. It
- * seems like there should be some bit somewhere describing this, but
- * after lots of experimentation I've come up empty-handed. For now we
- * assume that if the pointer is in the first half, then we're in
- * either the first or second state and use B, and otherwise we're in
- * the second or third state and use A. So far I haven't seen anything
- * that violates this assumption.
- */
-
- struct {
- uint32_t unk0;
- uint32_t padding0[7]; /* Mirrors of unk0 */
-
- struct {
- uint32_t chunk : 3;
- uint32_t first_block : 32 - 3;
- } writer[6];
- uint32_t padding1[2]; /* Mirrors of writer[4], writer[5] */
-
- uint32_t unk1;
- uint32_t padding2[7]; /* Mirrors of unk1 */
-
- uint32_t writer_second_block[6];
- uint32_t padding3[2];
-
- uint32_t unk2[6];
- uint32_t padding4[2];
-
- struct {
- uint32_t chunk : 3;
- uint32_t first_block : 32 - 3;
- } reader[6];
- uint32_t padding5[2]; /* Mirrors of reader[4], reader[5] */
-
- uint32_t unk3;
- uint32_t padding6[7]; /* Mirrors of unk3 */
-
- uint32_t reader_second_block[6];
- uint32_t padding7[2];
-
- uint32_t block_count[6];
- uint32_t padding[2];
-
- uint32_t unk4;
- uint32_t padding9[7]; /* Mirrors of unk4 */
- } data1;
-
- const uint32_t *data1_ptr = small_mem_pool ? &mempool[0xc00] : &mempool[0x1800];
- memcpy(&data1, data1_ptr, sizeof(data1));
-
- /* Based on the kernel, the first dword is the mem pool size (in
- * blocks?) and mirrors CP_MEM_POOL_DBG_SIZE.
- */
- const uint32_t *data2_ptr = small_mem_pool ? &mempool[0x1000] : &mempool[0x2000];
- const int data2_size = 0x60;
-
- /* This seems to be the size of each queue in chunks. */
- const uint32_t *queue_sizes = &data2_ptr[0x18];
-
- printf("\tdata2:\n");
- dump_hex_ascii(data2_ptr, 4 * data2_size, 1);
-
- /* These seem to be some kind of counter of allocated/deallocated blocks */
- if (verbose) {
- printf("\tunk0: %x\n", data1.unk0);
- printf("\tunk1: %x\n", data1.unk1);
- printf("\tunk3: %x\n", data1.unk3);
- printf("\tunk4: %x\n\n", data1.unk4);
- }
-
- for (int queue = 0; queue < num_queues; queue++) {
- const char *cluster_names[6] = {
- "FE", "SP_VS", "PC_VS", "GRAS", "SP_PS", "PS"
- };
- printf("\tCLUSTER_%s:\n\n", cluster_names[queue]);
-
- if (verbose) {
- printf("\t\twriter_first_block: 0x%x\n", data1.writer[queue].first_block);
- printf("\t\twriter_second_block: 0x%x\n", data1.writer_second_block[queue]);
- printf("\t\twriter_chunk: %d\n", data1.writer[queue].chunk);
- printf("\t\treader_first_block: 0x%x\n", data1.reader[queue].first_block);
- printf("\t\treader_second_block: 0x%x\n", data1.reader_second_block[queue]);
- printf("\t\treader_chunk: %d\n", data1.reader[queue].chunk);
- printf("\t\tblock_count: %d\n", data1.block_count[queue]);
- printf("\t\tunk2: 0x%x\n", data1.unk2[queue]);
- printf("\t\tqueue_size: %d\n\n", queue_sizes[queue]);
- }
-
- uint32_t cur_chunk = data1.reader[queue].chunk;
- uint32_t cur_block = cur_chunk > 3 ?
- data1.reader[queue].first_block :
- data1.reader_second_block[queue];
- uint32_t last_chunk = data1.writer[queue].chunk;
- uint32_t last_block = last_chunk > 3 ?
- data1.writer[queue].first_block :
- data1.writer_second_block[queue];
-
- if (verbose)
- printf("\tblock %x\n", cur_block);
- if (cur_block >= num_blocks) {
- fprintf(stderr, "block %x too large\n", cur_block);
- exit(1);
- }
- unsigned calculated_queue_size = 0;
- while (cur_block != last_block || cur_chunk != last_chunk) {
- calculated_queue_size++;
- uint32_t *chunk_ptr = &mempool[cur_block * 0x20 + cur_chunk * 4];
-
- dump_mem_pool_chunk(chunk_ptr);
-
- printf("\t%05x: %08x %08x %08x %08x\n",
- 4 * (cur_block * 0x20 + cur_chunk + 4),
- chunk_ptr[0], chunk_ptr[1], chunk_ptr[2], chunk_ptr[3]);
-
- cur_chunk++;
- if (cur_chunk == 8) {
- cur_block = next_pointers[cur_block];
- if (verbose)
- printf("\tblock %x\n", cur_block);
- if (cur_block >= num_blocks) {
- fprintf(stderr, "block %x too large\n", cur_block);
- exit(1);
- }
- cur_chunk = 0;
- }
- }
- if (calculated_queue_size != queue_sizes[queue]) {
- printf("\t\tCALCULATED SIZE %d DOES NOT MATCH!\n", calculated_queue_size);
- }
- printf("\n");
- }
+ /* The mem pool is a shared pool of memory used for storing in-flight
+ * register writes. There are 6 different queues, one for each
+ * cluster. Writing to $data (or for some special registers, $addr)
+ * pushes data onto the appropriate queue, and each queue is pulled
+ * from by the appropriate cluster. The queues are thus written to
+ * in-order, but may be read out-of-order.
+ *
+ * The queues are conceptually divided into 128-bit "chunks", and the
+ * read and write pointers are in units of chunks. These chunks are
+ * organized internally into 8-chunk "blocks", and memory is allocated
+ * dynamically in terms of blocks. Each queue is represented as a
+ * singly-linked list of blocks, as well as 3-bit start/end chunk
+ * pointers that point within the first/last block. The next pointers
+ * are located in a separate array, rather than inline.
+ */
+
+ /* TODO: The firmware CP_MEM_POOL save/restore routines do something
+ * like:
+ *
+ * cread $02, [ $00 + 0 ]
+ * and $02, $02, 0x118
+ * ...
+ * brne $02, 0, #label
+ * mov $03, 0x2000
+ * mov $03, 0x1000
+ * label:
+ * ...
+ *
+ * I think that control register 0 is the GPU version, and some
+ * versions have a smaller mem pool. It seems some models have a mem
+ * pool that's half the size, and a bunch of offsets are shifted
+ * accordingly. Unfortunately the kernel driver's dumping code doesn't
+ * seem to take this into account, even the downstream android driver,
+ * and we don't know which versions 0x8, 0x10, or 0x100 correspond
+ * to. Or maybe we can use CP_DBG_MEM_POOL_SIZE to figure this out?
+ */
+ bool small_mem_pool = false;
+
+ /* The array of next pointers for each block. */
+ const uint32_t *next_pointers =
+ small_mem_pool ? &mempool[0x800] : &mempool[0x1000];
+
+ /* Maximum number of blocks in the pool, also the size of the pointers
+ * array.
+ */
+ const int num_blocks = small_mem_pool ? 0x30 : 0x80;
+
+ /* Number of queues */
+ const unsigned num_queues = 6;
+
+ /* Unfortunately the per-queue state is a little more complicated than
+ * a simple pair of begin/end pointers. Instead of a single beginning
+ * block, there are *two*, with the property that either the two are
+ * equal or the second is the "next" of the first. Similarly there are
+ * two end blocks. Thus the queue either looks like this:
+ *
+ * A -> B -> ... -> C -> D
+ *
+ * Or like this, or some combination:
+ *
+ * A/B -> ... -> C/D
+ *
+ * However, there's only one beginning/end chunk offset. Now the
+ * question is, which of A or B is the actual start? I.e. is the chunk
+ * offset an offset inside A or B? It depends. I'll show a typical read
+ * cycle, starting here (read pointer marked with a *) with a chunk
+ * offset of 0:
+ *
+ * A B
+ * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ * |_|_|_|_|_|_|_|_| -> |*|_|_|_|_|_|_|_| -> |_|_|_|_|_|_|_|_|
+ *
+ * Once the pointer advances far enough, the hardware decides to free
+ * A, after which the read-side state looks like:
+ *
+ * (free) A/B
+ * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ * |_|_|_|_|_|_|_|_| |_|_|_|*|_|_|_|_| -> |_|_|_|_|_|_|_|_|
+ *
+ * Then after advancing the pointer a bit more, the hardware fetches
+ * the "next" pointer for A and stores it in B:
+ *
+ * (free) A B
+ * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ * |_|_|_|_|_|_|_|_| |_|_|_|_|_|_|_|*| -> |_|_|_|_|_|_|_|_|
+ *
+ * Then the read pointer advances into B, at which point we've come
+ * back to the first state having advanced a whole block:
+ *
+ * (free) A B
+ * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ * |_|_|_|_|_|_|_|_| |_|_|_|_|_|_|_|_| -> |*|_|_|_|_|_|_|_|
+ *
+ *
+ * There is a similar cycle for the write pointer. Now, the question
+ * is, how do we know which state we're in? We need to know this to
+ * know whether the pointer (*) is in A or B if they're different. It
+ * seems like there should be some bit somewhere describing this, but
+ * after lots of experimentation I've come up empty-handed. For now we
+ * assume that if the pointer is in the first half, then we're in
+ * either the first or second state and use B, and otherwise we're in
+ * the second or third state and use A. So far I haven't seen anything
+ * that violates this assumption.
+ */
+
+ struct {
+ uint32_t unk0;
+ uint32_t padding0[7]; /* Mirrors of unk0 */
+
+ struct {
+ uint32_t chunk : 3;
+ uint32_t first_block : 32 - 3;
+ } writer[6];
+ uint32_t padding1[2]; /* Mirrors of writer[4], writer[5] */
+
+ uint32_t unk1;
+ uint32_t padding2[7]; /* Mirrors of unk1 */
+
+ uint32_t writer_second_block[6];
+ uint32_t padding3[2];
+
+ uint32_t unk2[6];
+ uint32_t padding4[2];
+
+ struct {
+ uint32_t chunk : 3;
+ uint32_t first_block : 32 - 3;
+ } reader[6];
+ uint32_t padding5[2]; /* Mirrors of reader[4], reader[5] */
+
+ uint32_t unk3;
+ uint32_t padding6[7]; /* Mirrors of unk3 */
+
+ uint32_t reader_second_block[6];
+ uint32_t padding7[2];
+
+ uint32_t block_count[6];
+ uint32_t padding[2];
+
+ uint32_t unk4;
+ uint32_t padding9[7]; /* Mirrors of unk4 */
+ } data1;
+
+ const uint32_t *data1_ptr =
+ small_mem_pool ? &mempool[0xc00] : &mempool[0x1800];
+ memcpy(&data1, data1_ptr, sizeof(data1));
+
+ /* Based on the kernel, the first dword is the mem pool size (in
+ * blocks?) and mirrors CP_MEM_POOL_DBG_SIZE.
+ */
+ const uint32_t *data2_ptr =
+ small_mem_pool ? &mempool[0x1000] : &mempool[0x2000];
+ const int data2_size = 0x60;
+
+ /* This seems to be the size of each queue in chunks. */
+ const uint32_t *queue_sizes = &data2_ptr[0x18];
+
+ printf("\tdata2:\n");
+ dump_hex_ascii(data2_ptr, 4 * data2_size, 1);
+
+ /* These seem to be some kind of counter of allocated/deallocated blocks */
+ if (verbose) {
+ printf("\tunk0: %x\n", data1.unk0);
+ printf("\tunk1: %x\n", data1.unk1);
+ printf("\tunk3: %x\n", data1.unk3);
+ printf("\tunk4: %x\n\n", data1.unk4);
+ }
+
+ for (int queue = 0; queue < num_queues; queue++) {
+ const char *cluster_names[6] = {"FE", "SP_VS", "PC_VS",
+ "GRAS", "SP_PS", "PS"};
+ printf("\tCLUSTER_%s:\n\n", cluster_names[queue]);
+
+ if (verbose) {
+ printf("\t\twriter_first_block: 0x%x\n",
+ data1.writer[queue].first_block);
+ printf("\t\twriter_second_block: 0x%x\n",
+ data1.writer_second_block[queue]);
+ printf("\t\twriter_chunk: %d\n", data1.writer[queue].chunk);
+ printf("\t\treader_first_block: 0x%x\n",
+ data1.reader[queue].first_block);
+ printf("\t\treader_second_block: 0x%x\n",
+ data1.reader_second_block[queue]);
+ printf("\t\treader_chunk: %d\n", data1.reader[queue].chunk);
+ printf("\t\tblock_count: %d\n", data1.block_count[queue]);
+ printf("\t\tunk2: 0x%x\n", data1.unk2[queue]);
+ printf("\t\tqueue_size: %d\n\n", queue_sizes[queue]);
+ }
+
+ uint32_t cur_chunk = data1.reader[queue].chunk;
+ uint32_t cur_block = cur_chunk > 3 ? data1.reader[queue].first_block
+ : data1.reader_second_block[queue];
+ uint32_t last_chunk = data1.writer[queue].chunk;
+ uint32_t last_block = last_chunk > 3 ? data1.writer[queue].first_block
+ : data1.writer_second_block[queue];
+
+ if (verbose)
+ printf("\tblock %x\n", cur_block);
+ if (cur_block >= num_blocks) {
+ fprintf(stderr, "block %x too large\n", cur_block);
+ exit(1);
+ }
+ unsigned calculated_queue_size = 0;
+ while (cur_block != last_block || cur_chunk != last_chunk) {
+ calculated_queue_size++;
+ uint32_t *chunk_ptr = &mempool[cur_block * 0x20 + cur_chunk * 4];
+
+ dump_mem_pool_chunk(chunk_ptr);
+
+ printf("\t%05x: %08x %08x %08x %08x\n",
+ 4 * (cur_block * 0x20 + cur_chunk + 4), chunk_ptr[0],
+ chunk_ptr[1], chunk_ptr[2], chunk_ptr[3]);
+
+ cur_chunk++;
+ if (cur_chunk == 8) {
+ cur_block = next_pointers[cur_block];
+ if (verbose)
+ printf("\tblock %x\n", cur_block);
+ if (cur_block >= num_blocks) {
+ fprintf(stderr, "block %x too large\n", cur_block);
+ exit(1);
+ }
+ cur_chunk = 0;
+ }
+ }
+ if (calculated_queue_size != queue_sizes[queue]) {
+ printf("\t\tCALCULATED SIZE %d DOES NOT MATCH!\n",
+ calculated_queue_size);
+ }
+ printf("\n");
+ }
}
static void
decode_indexed_registers(void)
{
- char *name = NULL;
- uint32_t sizedwords = 0;
-
- foreach_line_in_section (line) {
- if (startswith(line, " - regs-name:")) {
- free(name);
- parseline(line, " - regs-name: %ms", &name);
- } else if (startswith(line, " dwords:")) {
- parseline(line, " dwords: %u", &sizedwords);
- } else if (startswith(line, " data: !!ascii85 |")) {
- uint32_t *buf = popline_ascii85(sizedwords);
-
- /* some of the sections are pretty large, and are (at least
- * so far) not useful, so skip them if not in verbose mode:
- */
- bool dump = verbose ||
- !strcmp(name, "CP_SQE_STAT") ||
- !strcmp(name, "CP_DRAW_STATE") ||
- !strcmp(name, "CP_ROQ") ||
- 0;
-
- if (!strcmp(name, "CP_SQE_STAT"))
- dump_cp_sqe_stat(buf);
-
- if (!strcmp(name, "CP_UCODE_DBG_DATA"))
- dump_cp_ucode_dbg(buf);
-
- if (!strcmp(name, "CP_MEMPOOL"))
- dump_cp_mem_pool(buf);
-
- if (dump)
- dump_hex_ascii(buf, 4 * sizedwords, 1);
-
- free(buf);
-
- continue;
- }
-
- printf("%s", line);
- }
+ char *name = NULL;
+ uint32_t sizedwords = 0;
+
+ foreach_line_in_section (line) {
+ if (startswith(line, " - regs-name:")) {
+ free(name);
+ parseline(line, " - regs-name: %ms", &name);
+ } else if (startswith(line, " dwords:")) {
+ parseline(line, " dwords: %u", &sizedwords);
+ } else if (startswith(line, " data: !!ascii85 |")) {
+ uint32_t *buf = popline_ascii85(sizedwords);
+
+ /* some of the sections are pretty large, and are (at least
+ * so far) not useful, so skip them if not in verbose mode:
+ */
+ bool dump = verbose || !strcmp(name, "CP_SQE_STAT") ||
+ !strcmp(name, "CP_DRAW_STATE") ||
+ !strcmp(name, "CP_ROQ") || 0;
+
+ if (!strcmp(name, "CP_SQE_STAT"))
+ dump_cp_sqe_stat(buf);
+
+ if (!strcmp(name, "CP_UCODE_DBG_DATA"))
+ dump_cp_ucode_dbg(buf);
+
+ if (!strcmp(name, "CP_MEMPOOL"))
+ dump_cp_mem_pool(buf);
+
+ if (dump)
+ dump_hex_ascii(buf, 4 * sizedwords, 1);
+
+ free(buf);
+
+ continue;
+ }
+
+ printf("%s", line);
+ }
}
/*
@@ -875,47 +892,45 @@ decode_indexed_registers(void)
static void
decode_shader_blocks(void)
{
- char *type = NULL;
- uint32_t sizedwords = 0;
-
- foreach_line_in_section (line) {
- if (startswith(line, " - type:")) {
- free(type);
- parseline(line, " - type: %ms", &type);
- } else if (startswith(line, " size:")) {
- parseline(line, " size: %u", &sizedwords);
- } else if (startswith(line, " data: !!ascii85 |")) {
- uint32_t *buf = popline_ascii85(sizedwords);
-
- /* some of the sections are pretty large, and are (at least
- * so far) not useful, so skip them if not in verbose mode:
- */
- bool dump = verbose ||
- !strcmp(type, "A6XX_SP_INST_DATA") ||
- !strcmp(type, "A6XX_HLSQ_INST_RAM") ||
- 0;
-
- if (!strcmp(type, "A6XX_SP_INST_DATA") ||
- !strcmp(type, "A6XX_HLSQ_INST_RAM")) {
- /* TODO this section actually contains multiple shaders
- * (or parts of shaders?), so perhaps we should search
- * for ends of shaders and decode each?
- */
- try_disasm_a3xx(buf, sizedwords, 1, stdout, options.gpu_id);
- }
-
- if (dump)
- dump_hex_ascii(buf, 4 * sizedwords, 1);
-
- free(buf);
-
- continue;
- }
-
- printf("%s", line);
- }
-
- free(type);
+ char *type = NULL;
+ uint32_t sizedwords = 0;
+
+ foreach_line_in_section (line) {
+ if (startswith(line, " - type:")) {
+ free(type);
+ parseline(line, " - type: %ms", &type);
+ } else if (startswith(line, " size:")) {
+ parseline(line, " size: %u", &sizedwords);
+ } else if (startswith(line, " data: !!ascii85 |")) {
+ uint32_t *buf = popline_ascii85(sizedwords);
+
+ /* some of the sections are pretty large, and are (at least
+ * so far) not useful, so skip them if not in verbose mode:
+ */
+ bool dump = verbose || !strcmp(type, "A6XX_SP_INST_DATA") ||
+ !strcmp(type, "A6XX_HLSQ_INST_RAM") || 0;
+
+ if (!strcmp(type, "A6XX_SP_INST_DATA") ||
+ !strcmp(type, "A6XX_HLSQ_INST_RAM")) {
+ /* TODO this section actually contains multiple shaders
+ * (or parts of shaders?), so perhaps we should search
+ * for ends of shaders and decode each?
+ */
+ try_disasm_a3xx(buf, sizedwords, 1, stdout, options.gpu_id);
+ }
+
+ if (dump)
+ dump_hex_ascii(buf, 4 * sizedwords, 1);
+
+ free(buf);
+
+ continue;
+ }
+
+ printf("%s", line);
+ }
+
+ free(type);
}
/*
@@ -925,34 +940,33 @@ decode_shader_blocks(void)
static void
decode_debugbus(void)
{
- char *block = NULL;
- uint32_t sizedwords = 0;
-
- foreach_line_in_section (line) {
- if (startswith(line, " - debugbus-block:")) {
- free(block);
- parseline(line, " - debugbus-block: %ms", &block);
- } else if (startswith(line, " count:")) {
- parseline(line, " count: %u", &sizedwords);
- } else if (startswith(line, " data: !!ascii85 |")) {
- uint32_t *buf = popline_ascii85(sizedwords);
-
- /* some of the sections are pretty large, and are (at least
- * so far) not useful, so skip them if not in verbose mode:
- */
- bool dump = verbose ||
- 0;
-
- if (dump)
- dump_hex_ascii(buf, 4 * sizedwords, 1);
-
- free(buf);
-
- continue;
- }
-
- printf("%s", line);
- }
+ char *block = NULL;
+ uint32_t sizedwords = 0;
+
+ foreach_line_in_section (line) {
+ if (startswith(line, " - debugbus-block:")) {
+ free(block);
+ parseline(line, " - debugbus-block: %ms", &block);
+ } else if (startswith(line, " count:")) {
+ parseline(line, " count: %u", &sizedwords);
+ } else if (startswith(line, " data: !!ascii85 |")) {
+ uint32_t *buf = popline_ascii85(sizedwords);
+
+ /* some of the sections are pretty large, and are (at least
+ * so far) not useful, so skip them if not in verbose mode:
+ */
+ bool dump = verbose || 0;
+
+ if (dump)
+ dump_hex_ascii(buf, 4 * sizedwords, 1);
+
+ free(buf);
+
+ continue;
+ }
+
+ printf("%s", line);
+ }
}
/*
@@ -962,52 +976,55 @@ decode_debugbus(void)
static void
decode(void)
{
- const char *line;
-
- while ((line = popline())) {
- printf("%s", line);
- if (startswith(line, "revision:")) {
- parseline(line, "revision: %u", &options.gpu_id);
- printf("Got gpu_id=%u\n", options.gpu_id);
-
- cffdec_init(&options);
-
- if (is_a6xx()) {
- rnn_gmu = rnn_new(!options.color);
- rnn_load_file(rnn_gmu, "adreno/a6xx_gmu.xml", "A6XX");
- rnn_control = rnn_new(!options.color);
- rnn_load_file(rnn_control, "adreno/adreno_control_regs.xml", "A6XX_CONTROL_REG");
- rnn_pipe = rnn_new(!options.color);
- rnn_load_file(rnn_pipe, "adreno/adreno_pipe_regs.xml", "A6XX_PIPE_REG");
- } else if (is_a5xx()) {
- rnn_control = rnn_new(!options.color);
- rnn_load_file(rnn_control, "adreno/adreno_control_regs.xml", "A5XX_CONTROL_REG");
- } else {
- rnn_control = NULL;
- }
- } else if (startswith(line, "bos:")) {
- decode_bos();
- } else if (startswith(line, "ringbuffer:")) {
- decode_ringbuffer();
- } else if (startswith(line, "registers:")) {
- decode_registers();
-
- /* after we've recorded buffer contents, and CP register values,
- * we can take a stab at decoding the cmdstream:
- */
- dump_cmdstream();
- } else if (startswith(line, "registers-gmu:")) {
- decode_gmu_registers();
- } else if (startswith(line, "indexed-registers:")) {
- decode_indexed_registers();
- } else if (startswith(line, "shader-blocks:")) {
- decode_shader_blocks();
- } else if (startswith(line, "clusters:")) {
- decode_clusters();
- } else if (startswith(line, "debugbus:")) {
- decode_debugbus();
- }
- }
+ const char *line;
+
+ while ((line = popline())) {
+ printf("%s", line);
+ if (startswith(line, "revision:")) {
+ parseline(line, "revision: %u", &options.gpu_id);
+ printf("Got gpu_id=%u\n", options.gpu_id);
+
+ cffdec_init(&options);
+
+ if (is_a6xx()) {
+ rnn_gmu = rnn_new(!options.color);
+ rnn_load_file(rnn_gmu, "adreno/a6xx_gmu.xml", "A6XX");
+ rnn_control = rnn_new(!options.color);
+ rnn_load_file(rnn_control, "adreno/adreno_control_regs.xml",
+ "A6XX_CONTROL_REG");
+ rnn_pipe = rnn_new(!options.color);
+ rnn_load_file(rnn_pipe, "adreno/adreno_pipe_regs.xml",
+ "A6XX_PIPE_REG");
+ } else if (is_a5xx()) {
+ rnn_control = rnn_new(!options.color);
+ rnn_load_file(rnn_control, "adreno/adreno_control_regs.xml",
+ "A5XX_CONTROL_REG");
+ } else {
+ rnn_control = NULL;
+ }
+ } else if (startswith(line, "bos:")) {
+ decode_bos();
+ } else if (startswith(line, "ringbuffer:")) {
+ decode_ringbuffer();
+ } else if (startswith(line, "registers:")) {
+ decode_registers();
+
+ /* after we've recorded buffer contents, and CP register values,
+ * we can take a stab at decoding the cmdstream:
+ */
+ dump_cmdstream();
+ } else if (startswith(line, "registers-gmu:")) {
+ decode_gmu_registers();
+ } else if (startswith(line, "indexed-registers:")) {
+ decode_indexed_registers();
+ } else if (startswith(line, "shader-blocks:")) {
+ decode_shader_blocks();
+ } else if (startswith(line, "clusters:")) {
+ decode_clusters();
+ } else if (startswith(line, "debugbus:")) {
+ decode_debugbus();
+ }
+ }
}
/*
@@ -1017,92 +1034,96 @@ decode(void)
static void
usage(void)
{
- fprintf(stderr, "Usage:\n\n"
- "\tcrashdec [-achmsv] [-f FILE]\n\n"
- "Options:\n"
- "\t-a, --allregs - show all registers (including ones not written since\n"
- "\t previous draw) at each draw\n"
- "\t-c, --color - use colors\n"
- "\t-f, --file=FILE - read input from specified file (rather than stdin)\n"
- "\t-h, --help - this usage message\n"
- "\t-m, --markers - try to decode CP_NOP string markers\n"
- "\t-s, --summary - don't show individual register writes, but just show\n"
- "\t register values on draws\n"
- "\t-v, --verbose - dump more verbose output, including contents of\n"
- "\t less interesting buffers\n"
- "\n"
- );
- exit(2);
+ /* clang-format off */
+ fprintf(stderr, "Usage:\n\n"
+ "\tcrashdec [-achmsv] [-f FILE]\n\n"
+ "Options:\n"
+ "\t-a, --allregs - show all registers (including ones not written since\n"
+ "\t previous draw) at each draw\n"
+ "\t-c, --color - use colors\n"
+ "\t-f, --file=FILE - read input from specified file (rather than stdin)\n"
+ "\t-h, --help - this usage message\n"
+ "\t-m, --markers - try to decode CP_NOP string markers\n"
+ "\t-s, --summary - don't show individual register writes, but just show\n"
+ "\t register values on draws\n"
+ "\t-v, --verbose - dump more verbose output, including contents of\n"
+ "\t less interesting buffers\n"
+ "\n"
+ );
+ /* clang-format on */
+ exit(2);
}
+/* clang-format off */
static const struct option opts[] = {
- { .name = "allregs", .has_arg = 0, NULL, 'a' },
- { .name = "color", .has_arg = 0, NULL, 'c' },
- { .name = "file", .has_arg = 1, NULL, 'f' },
- { .name = "help", .has_arg = 0, NULL, 'h' },
- { .name = "markers", .has_arg = 0, NULL, 'm' },
- { .name = "summary", .has_arg = 0, NULL, 's' },
- { .name = "verbose", .has_arg = 0, NULL, 'v' },
- {}
+ { .name = "allregs", .has_arg = 0, NULL, 'a' },
+ { .name = "color", .has_arg = 0, NULL, 'c' },
+ { .name = "file", .has_arg = 1, NULL, 'f' },
+ { .name = "help", .has_arg = 0, NULL, 'h' },
+ { .name = "markers", .has_arg = 0, NULL, 'm' },
+ { .name = "summary", .has_arg = 0, NULL, 's' },
+ { .name = "verbose", .has_arg = 0, NULL, 'v' },
+ {}
};
+/* clang-format on */
static bool interactive;
static void
cleanup(void)
{
- fflush(stdout);
+ fflush(stdout);
- if (interactive) {
- pager_close();
- }
+ if (interactive) {
+ pager_close();
+ }
}
int
main(int argc, char **argv)
{
- int c;
-
- interactive = isatty(STDOUT_FILENO);
- options.color = interactive;
-
- /* default to read from stdin: */
- in = stdin;
-
- while ((c = getopt_long(argc, argv, "acf:hmsv", opts, NULL)) != -1) {
- switch (c) {
- case 'a':
- options.allregs = true;
- break;
- case 'c':
- options.color = true;
- break;
- case 'f':
- in = fopen(optarg, "r");
- break;
- case 'm':
- options.decode_markers = true;
- break;
- case 's':
- options.summary = true;
- break;
- case 'v':
- verbose = true;
- break;
- case 'h':
- default:
- usage();
- }
- }
-
- disasm_a3xx_set_debug(PRINT_RAW);
-
- if (interactive) {
- pager_open();
- }
-
- atexit(cleanup);
-
- decode();
- cleanup();
+ int c;
+
+ interactive = isatty(STDOUT_FILENO);
+ options.color = interactive;
+
+ /* default to read from stdin: */
+ in = stdin;
+
+ while ((c = getopt_long(argc, argv, "acf:hmsv", opts, NULL)) != -1) {
+ switch (c) {
+ case 'a':
+ options.allregs = true;
+ break;
+ case 'c':
+ options.color = true;
+ break;
+ case 'f':
+ in = fopen(optarg, "r");
+ break;
+ case 'm':
+ options.decode_markers = true;
+ break;
+ case 's':
+ options.summary = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ disasm_a3xx_set_debug(PRINT_RAW);
+
+ if (interactive) {
+ pager_open();
+ }
+
+ atexit(cleanup);
+
+ decode();
+ cleanup();
}
diff --git a/src/freedreno/decode/io.c b/src/freedreno/decode/io.c
index 5fc5752b298..cddf84bafdd 100644
--- a/src/freedreno/decode/io.c
+++ b/src/freedreno/decode/io.c
@@ -26,138 +26,145 @@
* Rob Clark <robclark@freedesktop.org>
*/
+#include <archive.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <archive.h>
+#include <sys/types.h>
#include <archive_entry.h>
#include "io.h"
struct io {
- struct archive *a;
- struct archive_entry *entry;
- unsigned offset;
+ struct archive *a;
+ struct archive_entry *entry;
+ unsigned offset;
};
-static void io_error(struct io *io)
+static void
+io_error(struct io *io)
{
- fprintf(stderr, "%s\n", archive_error_string(io->a));
- io_close(io);
+ fprintf(stderr, "%s\n", archive_error_string(io->a));
+ io_close(io);
}
-static struct io * io_new(void)
+static struct io *
+io_new(void)
{
- struct io *io = calloc(1, sizeof(*io));
- int ret;
-
- if (!io)
- return NULL;
-
- io->a = archive_read_new();
- ret = archive_read_support_filter_gzip(io->a);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
-
- ret = archive_read_support_filter_none(io->a);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
-
- ret = archive_read_support_format_all(io->a);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
-
- ret = archive_read_support_format_raw(io->a);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
-
- return io;
+ struct io *io = calloc(1, sizeof(*io));
+ int ret;
+
+ if (!io)
+ return NULL;
+
+ io->a = archive_read_new();
+ ret = archive_read_support_filter_gzip(io->a);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
+
+ ret = archive_read_support_filter_none(io->a);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
+
+ ret = archive_read_support_format_all(io->a);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
+
+ ret = archive_read_support_format_raw(io->a);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
+
+ return io;
}
-struct io * io_open(const char *filename)
+struct io *
+io_open(const char *filename)
{
- struct io *io = io_new();
- int ret;
+ struct io *io = io_new();
+ int ret;
- if (!io)
- return NULL;
+ if (!io)
+ return NULL;
- ret = archive_read_open_filename(io->a, filename, 10240);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
+ ret = archive_read_open_filename(io->a, filename, 10240);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
- ret = archive_read_next_header(io->a, &io->entry);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
+ ret = archive_read_next_header(io->a, &io->entry);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
- return io;
+ return io;
}
-struct io * io_openfd(int fd)
+struct io *
+io_openfd(int fd)
{
- struct io *io = io_new();
- int ret;
+ struct io *io = io_new();
+ int ret;
- if (!io)
- return NULL;
+ if (!io)
+ return NULL;
- ret = archive_read_open_fd(io->a, fd, 10240);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
+ ret = archive_read_open_fd(io->a, fd, 10240);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
- ret = archive_read_next_header(io->a, &io->entry);
- if (ret != ARCHIVE_OK) {
- io_error(io);
- return NULL;
- }
+ ret = archive_read_next_header(io->a, &io->entry);
+ if (ret != ARCHIVE_OK) {
+ io_error(io);
+ return NULL;
+ }
- return io;
+ return io;
}
-void io_close(struct io *io)
+void
+io_close(struct io *io)
{
- archive_read_free(io->a);
- free(io);
+ archive_read_free(io->a);
+ free(io);
}
-unsigned io_offset(struct io *io)
+unsigned
+io_offset(struct io *io)
{
- return io->offset;
+ return io->offset;
}
#include <assert.h>
-int io_readn(struct io *io, void *buf, int nbytes)
+int
+io_readn(struct io *io, void *buf, int nbytes)
{
- char *ptr = buf;
- int ret = 0;
- while (nbytes > 0) {
- int n = archive_read_data(io->a, ptr, nbytes);
- if (n < 0) {
- fprintf(stderr, "%s\n", archive_error_string(io->a));
- return n;
- }
- if (n == 0)
- break;
- ptr += n;
- nbytes -= n;
- ret += n;
- io->offset += n;
- }
- return ret;
+ char *ptr = buf;
+ int ret = 0;
+ while (nbytes > 0) {
+ int n = archive_read_data(io->a, ptr, nbytes);
+ if (n < 0) {
+ fprintf(stderr, "%s\n", archive_error_string(io->a));
+ return n;
+ }
+ if (n == 0)
+ break;
+ ptr += n;
+ nbytes -= n;
+ ret += n;
+ io->offset += n;
+ }
+ return ret;
}
diff --git a/src/freedreno/decode/io.h b/src/freedreno/decode/io.h
index d26ba4b82ae..986a550b840 100644
--- a/src/freedreno/decode/io.h
+++ b/src/freedreno/decode/io.h
@@ -35,17 +35,16 @@
struct io;
-struct io * io_open(const char *filename);
-struct io * io_openfd(int fd);
+struct io *io_open(const char *filename);
+struct io *io_openfd(int fd);
void io_close(struct io *io);
unsigned io_offset(struct io *io);
int io_readn(struct io *io, void *buf, int nbytes);
-
static inline int
check_extension(const char *path, const char *ext)
{
- return strcmp(path + strlen(path) - strlen(ext), ext) == 0;
+ return strcmp(path + strlen(path) - strlen(ext), ext) == 0;
}
#endif /* IO_H_ */
diff --git a/src/freedreno/decode/pager.c b/src/freedreno/decode/pager.c
index fa07c10a17f..f1abbadd946 100644
--- a/src/freedreno/decode/pager.c
+++ b/src/freedreno/decode/pager.c
@@ -27,73 +27,72 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <unistd.h>
#include "pager.h"
static pid_t pager_pid;
-
static void
pager_death(int n)
{
- exit(0);
+ exit(0);
}
void
pager_open(void)
{
- int fd[2];
-
- if (pipe(fd) < 0) {
- fprintf(stderr, "Failed to create pager pipe: %m\n");
- exit(-1);
- }
-
- pager_pid = fork();
- if (pager_pid < 0) {
- fprintf(stderr, "Failed to fork pager: %m\n");
- exit(-1);
- }
-
- if (pager_pid == 0) {
- const char* less_opts;
-
- dup2(fd[0], STDIN_FILENO);
- close(fd[0]);
- close(fd[1]);
-
- less_opts = "FRSMKX";
- setenv("LESS", less_opts, 1);
-
- execlp("less", "less", NULL);
-
- } else {
- /* we want to kill the parent process when pager exits: */
- signal(SIGCHLD, pager_death);
- dup2(fd[1], STDOUT_FILENO);
- close(fd[0]);
- close(fd[1]);
- }
+ int fd[2];
+
+ if (pipe(fd) < 0) {
+ fprintf(stderr, "Failed to create pager pipe: %m\n");
+ exit(-1);
+ }
+
+ pager_pid = fork();
+ if (pager_pid < 0) {
+ fprintf(stderr, "Failed to fork pager: %m\n");
+ exit(-1);
+ }
+
+ if (pager_pid == 0) {
+ const char *less_opts;
+
+ dup2(fd[0], STDIN_FILENO);
+ close(fd[0]);
+ close(fd[1]);
+
+ less_opts = "FRSMKX";
+ setenv("LESS", less_opts, 1);
+
+ execlp("less", "less", NULL);
+
+ } else {
+ /* we want to kill the parent process when pager exits: */
+ signal(SIGCHLD, pager_death);
+ dup2(fd[1], STDOUT_FILENO);
+ close(fd[0]);
+ close(fd[1]);
+ }
}
int
pager_close(void)
{
- siginfo_t status;
+ siginfo_t status;
- close(STDOUT_FILENO);
+ close(STDOUT_FILENO);
- while (true) {
- memset(&status, 0, sizeof(status));
- if (waitid(P_PID, pager_pid, &status, WEXITED) < 0) {
- if (errno == EINTR)
- continue;
- return -errno;
- }
+ while (true) {
+ memset(&status, 0, sizeof(status));
+ if (waitid(P_PID, pager_pid, &status, WEXITED) < 0) {
+ if (errno == EINTR)
+ continue;
+ return -errno;
+ }
- return 0;
- }
+ return 0;
+ }
}
diff --git a/src/freedreno/decode/pgmdump.c b/src/freedreno/decode/pgmdump.c
index 9bac866e647..16566cd87da 100644
--- a/src/freedreno/decode/pgmdump.c
+++ b/src/freedreno/decode/pgmdump.c
@@ -21,227 +21,229 @@
* SOFTWARE.
*/
+#include <fcntl.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
+#include <sys/types.h>
-#include "redump.h"
#include "disasm.h"
#include "io.h"
+#include "redump.h"
#define ASCII_XOR 0xff
#include "util.h"
struct pgm_header {
- uint32_t size;
- uint32_t unknown1;
- uint32_t unknown2;
- uint32_t revision;
- uint32_t unknown4;
- uint32_t unknown5;
- uint32_t unknown6;
- uint32_t unknown7;
- uint32_t unknown8;
- uint32_t num_attribs;
- uint32_t num_uniforms;
- uint32_t num_samplers;
- uint32_t num_varyings;
- uint32_t num_uniformblocks;
+ uint32_t size;
+ uint32_t unknown1;
+ uint32_t unknown2;
+ uint32_t revision;
+ uint32_t unknown4;
+ uint32_t unknown5;
+ uint32_t unknown6;
+ uint32_t unknown7;
+ uint32_t unknown8;
+ uint32_t num_attribs;
+ uint32_t num_uniforms;
+ uint32_t num_samplers;
+ uint32_t num_varyings;
+ uint32_t num_uniformblocks;
};
struct vs_header {
- uint32_t unknown1; /* seems to be # of sections up to and including shader */
- uint32_t unknown2; /* seems to be low byte or so of SQ_PROGRAM_CNTL */
- uint32_t unknown3;
- uint32_t unknown4;
- uint32_t unknown5;
- uint32_t unknown6;
- uint32_t unknown7;
- uint32_t unknown8;
- uint32_t unknown9; /* seems to be # of sections following shader */
+ uint32_t unknown1; /* seems to be # of sections up to and including shader */
+ uint32_t unknown2; /* seems to be low byte or so of SQ_PROGRAM_CNTL */
+ uint32_t unknown3;
+ uint32_t unknown4;
+ uint32_t unknown5;
+ uint32_t unknown6;
+ uint32_t unknown7;
+ uint32_t unknown8;
+ uint32_t unknown9; /* seems to be # of sections following shader */
};
struct fs_header {
- uint32_t unknown1;
+ uint32_t unknown1;
};
/*
- // Covers a lot of type_info
- // varying, attribute, uniform, sampler
- type_info & 0xFF
- if ((type_info >> 8) == 0x8b) // vector
- 0x50 = vec2
- 0x51 = vec3
- 0x52 = vec4
- 0x53 = ivec2
- 0x54 = ivec3
- 0x55 = ivec4
- 0x56 = bool // Why is this in vector?
- 0x57 = bvec2
- 0x58 = bvec3
- 0x59 = bvec4
- 0x5a = mat2
- 0x5b = mat3
- 0x5c = mat4
- 0x5a = mat2x2 // Same as mat2
- 0x65 = mat2x3
- 0x66 = mat2x4
- 0x67 = mat3x2
- 0x5b = mat3x3 // Same as mat3
- 0x68 = mat3x4
- 0x69 = mat4x2
- 0x6a = mat4x3
- 0x5c = mat4x4 // same as mat4
- 0x5e = sampler2D
- 0x5f = sampler3D
- 0x60 = samplerCube // XXX: Doesn't work
- 0x62 = sampler2DShadow
- 0xc6 = uvec2
- 0xc7 = uvec3
- 0xc8 = uvec4
- else if ((type_info >> 8) == 0x8d) // GLES3 samplers
- 0xC1 = sampler2DArray
- 0xC4 = sampler2DArrayShadow
- 0xC5 = samplerCubeShadow
- 0xCA = isampler2D
- 0xCB = isampler3D
- 0xCC = isamplerCube
- 0xD2 = usampler2D
- 0xD3 = usampler3D
- 0xD4 = usamplerCube
- 0xD7 = isampler2DArray
- 0xD7 = usampler2DArray // Is the same as isampler2DArray?
- else // 0x14 = single
- 0x04 = int
- 0x05 = uint
- 0x06 = float
+ // Covers a lot of type_info
+ // varying, attribute, uniform, sampler
+ type_info & 0xFF
+ if ((type_info >> 8) == 0x8b) // vector
+ 0x50 = vec2
+ 0x51 = vec3
+ 0x52 = vec4
+ 0x53 = ivec2
+ 0x54 = ivec3
+ 0x55 = ivec4
+ 0x56 = bool // Why is this in vector?
+ 0x57 = bvec2
+ 0x58 = bvec3
+ 0x59 = bvec4
+ 0x5a = mat2
+ 0x5b = mat3
+ 0x5c = mat4
+ 0x5a = mat2x2 // Same as mat2
+ 0x65 = mat2x3
+ 0x66 = mat2x4
+ 0x67 = mat3x2
+ 0x5b = mat3x3 // Same as mat3
+ 0x68 = mat3x4
+ 0x69 = mat4x2
+ 0x6a = mat4x3
+ 0x5c = mat4x4 // same as mat4
+ 0x5e = sampler2D
+ 0x5f = sampler3D
+ 0x60 = samplerCube // XXX: Doesn't work
+ 0x62 = sampler2DShadow
+ 0xc6 = uvec2
+ 0xc7 = uvec3
+ 0xc8 = uvec4
+ else if ((type_info >> 8) == 0x8d) // GLES3 samplers
+ 0xC1 = sampler2DArray
+ 0xC4 = sampler2DArrayShadow
+ 0xC5 = samplerCubeShadow
+ 0xCA = isampler2D
+ 0xCB = isampler3D
+ 0xCC = isamplerCube
+ 0xD2 = usampler2D
+ 0xD3 = usampler3D
+ 0xD4 = usamplerCube
+ 0xD7 = isampler2DArray
+ 0xD7 = usampler2DArray // Is the same as isampler2DArray?
+ else // 0x14 = single
+ 0x04 = int
+ 0x05 = uint
+ 0x06 = float
*/
struct attribute {
- uint32_t type_info;
- uint32_t reg; /* seems to be the register the fetch instruction loads to */
- uint32_t const_idx; /* the CONST() indx value for sampler */
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t unknown4;
- uint32_t unknown5;
- char name[];
+ uint32_t type_info;
+ uint32_t reg; /* seems to be the register the fetch instruction loads to */
+ uint32_t const_idx; /* the CONST() indx value for sampler */
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t unknown4;
+ uint32_t unknown5;
+ char name[];
};
struct uniform {
- uint32_t type_info;
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t unknown4;
- uint32_t const_base; /* const base register (for uniforms that take more than one const reg, ie. matrices) */
- uint32_t unknown6;
- uint32_t const_reg; /* the const register holding the value */
- uint32_t unknown7;
- uint32_t unknown8;
- uint32_t unknown9;
- union {
- struct {
- char name[1];
- } v1;
- struct {
- uint32_t unknown10;
- uint32_t unknown11;
- uint32_t unknown12;
- char name[];
- } v2;
- };
+ uint32_t type_info;
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t unknown4;
+ uint32_t const_base; /* const base register (for uniforms that take more than
+ one const reg, ie. matrices) */
+ uint32_t unknown6;
+ uint32_t const_reg; /* the const register holding the value */
+ uint32_t unknown7;
+ uint32_t unknown8;
+ uint32_t unknown9;
+ union {
+ struct {
+ char name[1];
+ } v1;
+ struct {
+ uint32_t unknown10;
+ uint32_t unknown11;
+ uint32_t unknown12;
+ char name[];
+ } v2;
+ };
};
struct uniformblockmember {
- uint32_t type_info;
- uint32_t is_array;
- uint32_t array_size; /* elements in the array */
- uint32_t unknown2; /* Same as array_size */
- uint32_t unknown3; /* Seems to be a offset within UBO in vertex (by components) */
- uint32_t unknown4;
- uint32_t unknown5; /* Seems to be a offset within UBO in fragment (by vec4) */
- uint32_t unknown6;
- uint32_t unknown7;
- uint32_t unknown8;
- uint32_t unknown9; /* UBO block index? */
- uint32_t unknown10;
- uint32_t unknown11;
- uint32_t unknown12;
- char name[];
+ uint32_t type_info;
+ uint32_t is_array;
+ uint32_t array_size; /* elements in the array */
+ uint32_t unknown2; /* Same as array_size */
+ uint32_t
+ unknown3; /* Seems to be a offset within UBO in vertex (by components) */
+ uint32_t unknown4;
+ uint32_t
+ unknown5; /* Seems to be a offset within UBO in fragment (by vec4) */
+ uint32_t unknown6;
+ uint32_t unknown7;
+ uint32_t unknown8;
+ uint32_t unknown9; /* UBO block index? */
+ uint32_t unknown10;
+ uint32_t unknown11;
+ uint32_t unknown12;
+ char name[];
};
-struct uniformblock
-{
- uint32_t type_info;
- uint32_t unknown1;
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t unknown4;
- uint32_t num_members;
- uint32_t num_members2;
- uint32_t unknown5;
- uint32_t unknown6;
- uint32_t unknown7;
- char name[];
+struct uniformblock {
+ uint32_t type_info;
+ uint32_t unknown1;
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t unknown4;
+ uint32_t num_members;
+ uint32_t num_members2;
+ uint32_t unknown5;
+ uint32_t unknown6;
+ uint32_t unknown7;
+ char name[];
};
-
struct sampler {
- uint32_t type_info;
- uint32_t is_array;
- uint32_t array_size; /* elements in the array */
- uint32_t unknown4; /* same as array_size */
- uint32_t unknown5;
- uint32_t unknown6;
- uint32_t const_idx; /* the CONST() indx value for the sampler */
- uint32_t unknown7;
- char name[];
+ uint32_t type_info;
+ uint32_t is_array;
+ uint32_t array_size; /* elements in the array */
+ uint32_t unknown4; /* same as array_size */
+ uint32_t unknown5;
+ uint32_t unknown6;
+ uint32_t const_idx; /* the CONST() indx value for the sampler */
+ uint32_t unknown7;
+ char name[];
};
struct varying {
- uint32_t type_info;
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t reg; /* the register holding the value (on entry to the shader) */
- char name[];
+ uint32_t type_info;
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t reg; /* the register holding the value (on entry to the shader) */
+ char name[];
};
struct output {
- uint32_t type_info;
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t unknown4;
- uint32_t unknown5;
- uint32_t unknown6;
- uint32_t unknown7;
- uint32_t unknown8;
- char name[];
+ uint32_t type_info;
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t unknown4;
+ uint32_t unknown5;
+ uint32_t unknown6;
+ uint32_t unknown7;
+ uint32_t unknown8;
+ char name[];
};
struct constant {
- uint32_t unknown1;
- uint32_t unknown2;
- uint32_t unknown3;
- uint32_t const_idx;
- float val[];
+ uint32_t unknown1;
+ uint32_t unknown2;
+ uint32_t unknown3;
+ uint32_t const_idx;
+ float val[];
};
struct state {
- char *buf;
- int sz;
- struct pgm_header *hdr;
- struct attribute *attribs[32]; /* don't really know the upper limit.. */
- struct uniform *uniforms[32];
- struct sampler *samplers[32];
- struct varying *varyings[32];
- struct {
- struct uniformblock *header;
- struct uniformblockmember **members; /* GL ES 3.0 spec mandates minimum 16K support. a3xx supports 65K */
- } uniformblocks[24]; /* Maximum a330 supports */
- struct output *outputs[0]; /* I guess only one?? */
+ char *buf;
+ int sz;
+ struct pgm_header *hdr;
+ struct attribute *attribs[32]; /* don't really know the upper limit.. */
+ struct uniform *uniforms[32];
+ struct sampler *samplers[32];
+ struct varying *varyings[32];
+ struct {
+ struct uniformblock *header;
+ struct uniformblockmember **members; /* GL ES 3.0 spec mandates minimum
+ 16K support. a3xx supports 65K */
+ } uniformblocks[24]; /* Maximum a330 supports */
+ struct output *outputs[0]; /* I guess only one?? */
};
static const char *infile;
@@ -249,810 +251,844 @@ static int full_dump = 1;
static int dump_shaders = 0;
static int gpu_id;
-static char *find_sect_end(char *buf, int sz)
+static char *
+find_sect_end(char *buf, int sz)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz - 3;
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz - 3;
- while (ptr < end) {
- uint32_t d = 0;
+ while (ptr < end) {
+ uint32_t d = 0;
- d |= ptr[0] << 0;
- d |= ptr[1] << 8;
- d |= ptr[2] << 16;
- d |= ptr[3] << 24;
+ d |= ptr[0] << 0;
+ d |= ptr[1] << 8;
+ d |= ptr[2] << 16;
+ d |= ptr[3] << 24;
- /* someone at QC likes baseball */
- if (d == 0xba5eba11)
- return (char *)ptr;
+ /* someone at QC likes baseball */
+ if (d == 0xba5eba11)
+ return (char *)ptr;
- ptr++;
- }
- return NULL;
+ ptr++;
+ }
+ return NULL;
}
-static void *next_sect(struct state *state, int *sect_size)
+static void *
+next_sect(struct state *state, int *sect_size)
{
- char *end = find_sect_end(state->buf, state->sz);
- void *sect;
+ char *end = find_sect_end(state->buf, state->sz);
+ void *sect;
- if (!end)
- return NULL;
+ if (!end)
+ return NULL;
- *sect_size = end - state->buf;
+ *sect_size = end - state->buf;
- /* copy the section to keep things nicely 32b aligned: */
- sect = malloc(ALIGN(*sect_size, 4));
- memcpy(sect, state->buf, *sect_size);
+ /* copy the section to keep things nicely 32b aligned: */
+ sect = malloc(ALIGN(*sect_size, 4));
+ memcpy(sect, state->buf, *sect_size);
- state->sz -= *sect_size + 4;
- state->buf = end + 4;
+ state->sz -= *sect_size + 4;
+ state->buf = end + 4;
- return sect;
+ return sect;
}
-static int valid_type(uint32_t type_info)
+static int
+valid_type(uint32_t type_info)
{
- switch ((type_info >> 8) & 0xff) {
- case 0x8b: /* vector */
- case 0x8d: /* GLES3 samplers */
- case 0x14: /* float */
- return 1;
- default:
- return 0;
- }
+ switch ((type_info >> 8) & 0xff) {
+ case 0x8b: /* vector */
+ case 0x8d: /* GLES3 samplers */
+ case 0x14: /* float */
+ return 1;
+ default:
+ return 0;
+ }
}
#if 0
static int valid_uniformblock(uint32_t type_info)
{
- if (type_info == 0x128)
- return 1;
- return 0;
+ if (type_info == 0x128)
+ return 1;
+ return 0;
}
#endif
-static void dump_attribute(struct attribute *attrib)
+static void
+dump_attribute(struct attribute *attrib)
{
- printf("\tR%d, CONST(%d): %s\n", attrib->reg,
- attrib->const_idx, attrib->name);
+ printf("\tR%d, CONST(%d): %s\n", attrib->reg, attrib->const_idx,
+ attrib->name);
}
-static inline int is_uniform_v2(struct uniform *uniform)
+static inline int
+is_uniform_v2(struct uniform *uniform)
{
- /* TODO maybe this should be based on revision #? */
- if (uniform->v2.unknown10 == 0)
- return 1;
- return 0;
+ /* TODO maybe this should be based on revision #? */
+ if (uniform->v2.unknown10 == 0)
+ return 1;
+ return 0;
}
-static void dump_uniform(struct uniform *uniform)
+static void
+dump_uniform(struct uniform *uniform)
{
- char *name = is_uniform_v2(uniform) ? uniform->v2.name : uniform->v1.name;
- if (uniform->const_reg == -1) {
- printf("\tC%d+: %s\n", uniform->const_base, name);
- } else {
- printf("\tC%d: %s\n", uniform->const_reg, name);
- }
+ char *name = is_uniform_v2(uniform) ? uniform->v2.name : uniform->v1.name;
+ if (uniform->const_reg == -1) {
+ printf("\tC%d+: %s\n", uniform->const_base, name);
+ } else {
+ printf("\tC%d: %s\n", uniform->const_reg, name);
+ }
}
-static void dump_sampler(struct sampler *sampler)
+static void
+dump_sampler(struct sampler *sampler)
{
- printf("\tCONST(%d): %s\n", sampler->const_idx, sampler->name);
+ printf("\tCONST(%d): %s\n", sampler->const_idx, sampler->name);
}
-static void dump_varying(struct varying *varying)
+static void
+dump_varying(struct varying *varying)
{
- printf("\tR%d: %s\n", varying->reg, varying->name);
+ printf("\tR%d: %s\n", varying->reg, varying->name);
}
-static void dump_uniformblock(struct uniformblock *uniformblock)
+static void
+dump_uniformblock(struct uniformblock *uniformblock)
{
- printf("\tUniform Block: %s(%d)\n", uniformblock->name, uniformblock->num_members);
+ printf("\tUniform Block: %s(%d)\n", uniformblock->name,
+ uniformblock->num_members);
}
-static void dump_uniformblockmember(struct uniformblockmember *member)
+static void
+dump_uniformblockmember(struct uniformblockmember *member)
{
- printf("Uniform Block member: %s\n", member->name);
+ printf("Uniform Block member: %s\n", member->name);
}
-static void dump_output(struct output *output)
+static void
+dump_output(struct output *output)
{
- printf("\tR?: %s\n", output->name);
+ printf("\tR?: %s\n", output->name);
}
-static void dump_constant(struct constant *constant)
+static void
+dump_constant(struct constant *constant)
{
- printf("\tC%d: %f, %f, %f, %f\n", constant->const_idx,
- constant->val[0], constant->val[1],
- constant->val[2], constant->val[3]);
+ printf("\tC%d: %f, %f, %f, %f\n", constant->const_idx, constant->val[0],
+ constant->val[1], constant->val[2], constant->val[3]);
}
/* dump attr/uniform/sampler/varying/const summary: */
-static void dump_short_summary(struct state *state, int nconsts,
- struct constant **constants)
+static void
+dump_short_summary(struct state *state, int nconsts,
+ struct constant **constants)
{
- int i;
-
- /* dump attr/uniform/sampler/varying/const summary: */
- for (i = 0; i < state->hdr->num_varyings; i++) {
- dump_varying(state->varyings[i]);
- }
- for (i = 0; i < state->hdr->num_attribs; i++) {
- dump_attribute(state->attribs[i]);
- }
- for (i = 0; i < state->hdr->num_uniforms; i++) {
- dump_uniform(state->uniforms[i]);
- }
- for (i = 0; i < state->hdr->num_samplers; i++) {
- dump_sampler(state->samplers[i]);
- }
- for (i = 0; i < nconsts - 1; i++) {
- if (constants[i]->unknown2 == 0) {
- dump_constant(constants[i]);
- }
- }
- printf("\n");
+ int i;
+
+ /* dump attr/uniform/sampler/varying/const summary: */
+ for (i = 0; i < state->hdr->num_varyings; i++) {
+ dump_varying(state->varyings[i]);
+ }
+ for (i = 0; i < state->hdr->num_attribs; i++) {
+ dump_attribute(state->attribs[i]);
+ }
+ for (i = 0; i < state->hdr->num_uniforms; i++) {
+ dump_uniform(state->uniforms[i]);
+ }
+ for (i = 0; i < state->hdr->num_samplers; i++) {
+ dump_sampler(state->samplers[i]);
+ }
+ for (i = 0; i < nconsts - 1; i++) {
+ if (constants[i]->unknown2 == 0) {
+ dump_constant(constants[i]);
+ }
+ }
+ printf("\n");
}
-static void dump_raw_shader(uint32_t *dwords, uint32_t sizedwords, int n, char *ext)
+static void
+dump_raw_shader(uint32_t *dwords, uint32_t sizedwords, int n, char *ext)
{
- static char filename[256];
- int fd;
-
- if (!dump_shaders)
- return;
-
- sprintf(filename, "%.*s-%d.%s", (int)strlen(infile)-3, infile, n, ext);
- fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
- if (fd != -1) {
- write(fd, dwords, sizedwords * 4);
- close(fd);
- }
+ static char filename[256];
+ int fd;
+
+ if (!dump_shaders)
+ return;
+
+ sprintf(filename, "%.*s-%d.%s", (int)strlen(infile) - 3, infile, n, ext);
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
+ if (fd != -1) {
+ write(fd, dwords, sizedwords * 4);
+ close(fd);
+ }
}
-static void dump_shaders_a2xx(struct state *state)
+static void
+dump_shaders_a2xx(struct state *state)
{
- int i, sect_size;
- uint8_t *ptr;
-
- /* dump vertex shaders: */
- for (i = 0; i < 3; i++) {
- struct vs_header *vs_hdr = next_sect(state, &sect_size);
- struct constant *constants[32];
- int j, level = 0;
-
- printf("\n");
-
- if (full_dump) {
- printf("#######################################################\n");
- printf("######## VS%d HEADER: (size %d)\n", i, sect_size);
- dump_hex((void *)vs_hdr, sect_size);
- }
-
- for (j = 0; j < (int)vs_hdr->unknown1 - 1; j++) {
- constants[j] = next_sect(state, &sect_size);
- if (full_dump) {
- printf("######## VS%d CONST: (size=%d)\n", i, sect_size);
- dump_constant(constants[j]);
- dump_hex((char *)constants[j], sect_size);
- }
- }
-
- ptr = next_sect(state, &sect_size);
- printf("######## VS%d SHADER: (size=%d)\n", i, sect_size);
- if (full_dump) {
- dump_hex(ptr, sect_size);
- level = 1;
- } else {
- dump_short_summary(state, vs_hdr->unknown1 - 1, constants);
- }
- disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level+1, MESA_SHADER_VERTEX);
- dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "vo");
- free(ptr);
-
- for (j = 0; j < vs_hdr->unknown9; j++) {
- ptr = next_sect(state, &sect_size);
- if (full_dump) {
- printf("######## VS%d CONST?: (size=%d)\n", i, sect_size);
- dump_hex(ptr, sect_size);
- }
- free(ptr);
- }
-
- for (j = 0; j < vs_hdr->unknown1 - 1; j++) {
- free(constants[j]);
- }
-
- free(vs_hdr);
- }
-
- /* dump fragment shaders: */
- for (i = 0; i < 1; i++) {
- struct fs_header *fs_hdr = next_sect(state, &sect_size);
- struct constant *constants[32];
- int j, level = 0;
-
- printf("\n");
-
- if (full_dump) {
- printf("#######################################################\n");
- printf("######## FS%d HEADER: (size %d)\n", i, sect_size);
- dump_hex((void *)fs_hdr, sect_size);
- }
-
- for (j = 0; j < fs_hdr->unknown1 - 1; j++) {
- constants[j] = next_sect(state, &sect_size);
- if (full_dump) {
- printf("######## FS%d CONST: (size=%d)\n", i, sect_size);
- dump_constant(constants[j]);
- dump_hex((char *)constants[j], sect_size);
- }
- }
-
- ptr = next_sect(state, &sect_size);
- printf("######## FS%d SHADER: (size=%d)\n", i, sect_size);
- if (full_dump) {
- dump_hex(ptr, sect_size);
- level = 1;
- } else {
- dump_short_summary(state, fs_hdr->unknown1 - 1, constants);
- }
- disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level+1, MESA_SHADER_FRAGMENT);
- dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "fo");
- free(ptr);
-
- for (j = 0; j < fs_hdr->unknown1 - 1; j++) {
- free(constants[j]);
- }
-
- free(fs_hdr);
- }
+ int i, sect_size;
+ uint8_t *ptr;
+
+ /* dump vertex shaders: */
+ for (i = 0; i < 3; i++) {
+ struct vs_header *vs_hdr = next_sect(state, &sect_size);
+ struct constant *constants[32];
+ int j, level = 0;
+
+ printf("\n");
+
+ if (full_dump) {
+ printf("#######################################################\n");
+ printf("######## VS%d HEADER: (size %d)\n", i, sect_size);
+ dump_hex((void *)vs_hdr, sect_size);
+ }
+
+ for (j = 0; j < (int)vs_hdr->unknown1 - 1; j++) {
+ constants[j] = next_sect(state, &sect_size);
+ if (full_dump) {
+ printf("######## VS%d CONST: (size=%d)\n", i, sect_size);
+ dump_constant(constants[j]);
+ dump_hex((char *)constants[j], sect_size);
+ }
+ }
+
+ ptr = next_sect(state, &sect_size);
+ printf("######## VS%d SHADER: (size=%d)\n", i, sect_size);
+ if (full_dump) {
+ dump_hex(ptr, sect_size);
+ level = 1;
+ } else {
+ dump_short_summary(state, vs_hdr->unknown1 - 1, constants);
+ }
+ disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level + 1,
+ MESA_SHADER_VERTEX);
+ dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "vo");
+ free(ptr);
+
+ for (j = 0; j < vs_hdr->unknown9; j++) {
+ ptr = next_sect(state, &sect_size);
+ if (full_dump) {
+ printf("######## VS%d CONST?: (size=%d)\n", i, sect_size);
+ dump_hex(ptr, sect_size);
+ }
+ free(ptr);
+ }
+
+ for (j = 0; j < vs_hdr->unknown1 - 1; j++) {
+ free(constants[j]);
+ }
+
+ free(vs_hdr);
+ }
+
+ /* dump fragment shaders: */
+ for (i = 0; i < 1; i++) {
+ struct fs_header *fs_hdr = next_sect(state, &sect_size);
+ struct constant *constants[32];
+ int j, level = 0;
+
+ printf("\n");
+
+ if (full_dump) {
+ printf("#######################################################\n");
+ printf("######## FS%d HEADER: (size %d)\n", i, sect_size);
+ dump_hex((void *)fs_hdr, sect_size);
+ }
+
+ for (j = 0; j < fs_hdr->unknown1 - 1; j++) {
+ constants[j] = next_sect(state, &sect_size);
+ if (full_dump) {
+ printf("######## FS%d CONST: (size=%d)\n", i, sect_size);
+ dump_constant(constants[j]);
+ dump_hex((char *)constants[j], sect_size);
+ }
+ }
+
+ ptr = next_sect(state, &sect_size);
+ printf("######## FS%d SHADER: (size=%d)\n", i, sect_size);
+ if (full_dump) {
+ dump_hex(ptr, sect_size);
+ level = 1;
+ } else {
+ dump_short_summary(state, fs_hdr->unknown1 - 1, constants);
+ }
+ disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level + 1,
+ MESA_SHADER_FRAGMENT);
+ dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "fo");
+ free(ptr);
+
+ for (j = 0; j < fs_hdr->unknown1 - 1; j++) {
+ free(constants[j]);
+ }
+
+ free(fs_hdr);
+ }
}
-static void dump_shaders_a3xx(struct state *state)
+static void
+dump_shaders_a3xx(struct state *state)
{
- int i, j;
-
- /* dump vertex shaders: */
- for (i = 0; i < 2; i++) {
- int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0;
- uint8_t *vs_hdr;
- struct constant *constants[32];
- uint8_t *instrs = NULL;
-
- vs_hdr = next_sect(state, &hdr_size);
-printf("hdr_size=%d\n", hdr_size);
-
- /* seems like there are two cases, either:
- * 1) 152 byte header,
- * 2) zero or more 32 byte compiler const sections
- * 3) followed by shader instructions
- * or, if there are no compiler consts, this can be
- * all smashed in one large section
- */
- int n;
- if (state->hdr->revision >= 0xb)
- n = 160;
- else if (state->hdr->revision >= 7)
- n = 156;
- else
- n = 152;
- if (hdr_size > n) {
- instrs = &vs_hdr[n];
- instrs_size = hdr_size - n;
- hdr_size = n;
- compact = 1;
- } else {
- while (1) {
- void *ptr = next_sect(state, &sect_size);
-
- if ((sect_size != 32) && (sect_size != 44)) {
- /* end of constants: */
- instrs = ptr;
- instrs_size = sect_size;
- break;
- }
- dump_hex_ascii(ptr, sect_size, 0);
- constants[nconsts++] = ptr;
- }
- }
-
- printf("\n");
-
- if (full_dump) {
- printf("#######################################################\n");
- printf("######## VS%d HEADER: (size %d)\n", i, hdr_size);
- dump_hex((void *)vs_hdr, hdr_size);
- for (j = 0; j < nconsts; j++) {
- printf("######## VS%d CONST: (size=%d)\n", i, (int)sizeof(constants[i]));
- dump_constant(constants[j]);
- dump_hex((char *)constants[j], sizeof(constants[j]));
- }
- }
-
- printf("######## VS%d SHADER: (size=%d)\n", i, instrs_size);
- if (full_dump) {
- dump_hex(instrs, instrs_size);
- level = 1;
- } else {
- dump_short_summary(state, nconsts, constants);
- }
-
- if (!compact) {
- if (state->hdr->revision >= 7) {
- instrs += ALIGN(instrs_size, 8) - instrs_size;
- instrs_size = ALIGN(instrs_size, 8);
- }
- instrs += 32;
- instrs_size -= 32;
- }
-
- disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level+1, stdout, gpu_id);
- dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "vo3");
- free(vs_hdr);
- }
-
- /* dump fragment shaders: */
- for (i = 0; i < 1; i++) {
- int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0;
- uint8_t *fs_hdr;
- struct constant *constants[32];
- uint8_t *instrs = NULL;
-
- fs_hdr = next_sect(state, &hdr_size);
-
-printf("hdr_size=%d\n", hdr_size);
- /* two cases, similar to vertex shader, but magic # is 200
- * (or 208 for newer?)..
- */
- int n;
- if (state->hdr->revision >= 0xb)
- n = 256;
- else if (state->hdr->revision >= 8)
- n = 208;
- else if (state->hdr->revision == 7)
- n = 204;
- else
- n = 200;
-
- if (hdr_size > n) {
- instrs = &fs_hdr[n];
- instrs_size = hdr_size - n;
- hdr_size = n;
- compact = 1;
- } else {
- while (1) {
- void *ptr = next_sect(state, &sect_size);
-
- if ((sect_size != 32) && (sect_size != 44)) {
- /* end of constants: */
- instrs = ptr;
- instrs_size = sect_size;
- break;
- }
-
- dump_hex_ascii(ptr, sect_size, 0);
- constants[nconsts++] = ptr;
- }
- }
-
- printf("\n");
-
- if (full_dump) {
- printf("#######################################################\n");
- printf("######## FS%d HEADER: (size %d)\n", i, hdr_size);
- dump_hex((void *)fs_hdr, hdr_size);
- for (j = 0; j < nconsts; j++) {
- printf("######## FS%d CONST: (size=%d)\n", i, (int)sizeof(constants[i]));
- dump_constant(constants[j]);
- dump_hex((char *)constants[j], sizeof(constants[j]));
- }
- }
-
- printf("######## FS%d SHADER: (size=%d)\n", i, instrs_size);
- if (full_dump) {
- dump_hex(instrs, instrs_size);
- level = 1;
- } else {
- dump_short_summary(state, nconsts, constants);
- }
-
- if (!compact) {
- if (state->hdr->revision >= 7) {
- instrs += 44;
- instrs_size -= 44;
- } else {
- instrs += 32;
- instrs_size -= 32;
- }
- }
- disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level+1, stdout, gpu_id);
- dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "fo3");
- free(fs_hdr);
- }
+ int i, j;
+
+ /* dump vertex shaders: */
+ for (i = 0; i < 2; i++) {
+ int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0;
+ uint8_t *vs_hdr;
+ struct constant *constants[32];
+ uint8_t *instrs = NULL;
+
+ vs_hdr = next_sect(state, &hdr_size);
+ printf("hdr_size=%d\n", hdr_size);
+
+ /* seems like there are two cases, either:
+ * 1) 152 byte header,
+ * 2) zero or more 32 byte compiler const sections
+ * 3) followed by shader instructions
+ * or, if there are no compiler consts, this can be
+ * all smashed in one large section
+ */
+ int n;
+ if (state->hdr->revision >= 0xb)
+ n = 160;
+ else if (state->hdr->revision >= 7)
+ n = 156;
+ else
+ n = 152;
+ if (hdr_size > n) {
+ instrs = &vs_hdr[n];
+ instrs_size = hdr_size - n;
+ hdr_size = n;
+ compact = 1;
+ } else {
+ while (1) {
+ void *ptr = next_sect(state, &sect_size);
+
+ if ((sect_size != 32) && (sect_size != 44)) {
+ /* end of constants: */
+ instrs = ptr;
+ instrs_size = sect_size;
+ break;
+ }
+ dump_hex_ascii(ptr, sect_size, 0);
+ constants[nconsts++] = ptr;
+ }
+ }
+
+ printf("\n");
+
+ if (full_dump) {
+ printf("#######################################################\n");
+ printf("######## VS%d HEADER: (size %d)\n", i, hdr_size);
+ dump_hex((void *)vs_hdr, hdr_size);
+ for (j = 0; j < nconsts; j++) {
+ printf("######## VS%d CONST: (size=%d)\n", i,
+ (int)sizeof(constants[i]));
+ dump_constant(constants[j]);
+ dump_hex((char *)constants[j], sizeof(constants[j]));
+ }
+ }
+
+ printf("######## VS%d SHADER: (size=%d)\n", i, instrs_size);
+ if (full_dump) {
+ dump_hex(instrs, instrs_size);
+ level = 1;
+ } else {
+ dump_short_summary(state, nconsts, constants);
+ }
+
+ if (!compact) {
+ if (state->hdr->revision >= 7) {
+ instrs += ALIGN(instrs_size, 8) - instrs_size;
+ instrs_size = ALIGN(instrs_size, 8);
+ }
+ instrs += 32;
+ instrs_size -= 32;
+ }
+
+ disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level + 1, stdout,
+ gpu_id);
+ dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "vo3");
+ free(vs_hdr);
+ }
+
+ /* dump fragment shaders: */
+ for (i = 0; i < 1; i++) {
+ int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0;
+ uint8_t *fs_hdr;
+ struct constant *constants[32];
+ uint8_t *instrs = NULL;
+
+ fs_hdr = next_sect(state, &hdr_size);
+
+ printf("hdr_size=%d\n", hdr_size);
+ /* two cases, similar to vertex shader, but magic # is 200
+ * (or 208 for newer?)..
+ */
+ int n;
+ if (state->hdr->revision >= 0xb)
+ n = 256;
+ else if (state->hdr->revision >= 8)
+ n = 208;
+ else if (state->hdr->revision == 7)
+ n = 204;
+ else
+ n = 200;
+
+ if (hdr_size > n) {
+ instrs = &fs_hdr[n];
+ instrs_size = hdr_size - n;
+ hdr_size = n;
+ compact = 1;
+ } else {
+ while (1) {
+ void *ptr = next_sect(state, &sect_size);
+
+ if ((sect_size != 32) && (sect_size != 44)) {
+ /* end of constants: */
+ instrs = ptr;
+ instrs_size = sect_size;
+ break;
+ }
+
+ dump_hex_ascii(ptr, sect_size, 0);
+ constants[nconsts++] = ptr;
+ }
+ }
+
+ printf("\n");
+
+ if (full_dump) {
+ printf("#######################################################\n");
+ printf("######## FS%d HEADER: (size %d)\n", i, hdr_size);
+ dump_hex((void *)fs_hdr, hdr_size);
+ for (j = 0; j < nconsts; j++) {
+ printf("######## FS%d CONST: (size=%d)\n", i,
+ (int)sizeof(constants[i]));
+ dump_constant(constants[j]);
+ dump_hex((char *)constants[j], sizeof(constants[j]));
+ }
+ }
+
+ printf("######## FS%d SHADER: (size=%d)\n", i, instrs_size);
+ if (full_dump) {
+ dump_hex(instrs, instrs_size);
+ level = 1;
+ } else {
+ dump_short_summary(state, nconsts, constants);
+ }
+
+ if (!compact) {
+ if (state->hdr->revision >= 7) {
+ instrs += 44;
+ instrs_size -= 44;
+ } else {
+ instrs += 32;
+ instrs_size -= 32;
+ }
+ }
+ disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level + 1, stdout,
+ gpu_id);
+ dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "fo3");
+ free(fs_hdr);
+ }
}
-static void dump_program(struct state *state)
+static void
+dump_program(struct state *state)
{
- int i, sect_size;
- uint8_t *ptr;
-
- state->hdr = next_sect(state, &sect_size);
-
- printf("######## HEADER: (size %d)\n", sect_size);
- printf("\tsize: %d\n", state->hdr->size);
- printf("\trevision: %d\n", state->hdr->revision);
- printf("\tattributes: %d\n", state->hdr->num_attribs);
- printf("\tuniforms: %d\n", state->hdr->num_uniforms);
- printf("\tsamplers: %d\n", state->hdr->num_samplers);
- printf("\tvaryings: %d\n", state->hdr->num_varyings);
- printf("\tuniform blocks: %d\n", state->hdr->num_uniformblocks);
- if (full_dump)
- dump_hex((void *)state->hdr, sect_size);
- printf("\n");
-
- /* there seems to be two 0xba5eba11's at the end of the header, possibly
- * with some other stuff between them:
- */
- ptr = next_sect(state, &sect_size);
- if (full_dump) {
- dump_hex_ascii(ptr, sect_size, 0);
- }
-
- for (i = 0; (i < state->hdr->num_attribs) && (state->sz > 0); i++) {
- state->attribs[i] = next_sect(state, &sect_size);
-
- /* hmm, for a3xx (or maybe just newer driver version), we have some
- * extra sections that don't seem useful, so skip these:
- */
- while (!valid_type(state->attribs[i]->type_info)) {
- dump_hex_ascii(state->attribs[i], sect_size, 0);
- state->attribs[i] = next_sect(state, &sect_size);
- }
-
- clean_ascii(state->attribs[i]->name, sect_size - 28);
- if (full_dump) {
- printf("######## ATTRIBUTE: (size %d)\n", sect_size);
- dump_attribute(state->attribs[i]);
- dump_hex((char *)state->attribs[i], sect_size);
- }
- }
-
- for (i = 0; (i < state->hdr->num_uniforms) && (state->sz > 0); i++) {
- state->uniforms[i] = next_sect(state, &sect_size);
-
- /* hmm, for a3xx (or maybe just newer driver version), we have some
- * extra sections that don't seem useful, so skip these:
- */
- while (!valid_type(state->uniforms[i]->type_info)) {
- dump_hex_ascii(state->uniforms[i], sect_size, 0);
- state->uniforms[i] = next_sect(state, &sect_size);
- }
-
- if (is_uniform_v2(state->uniforms[i])) {
- clean_ascii(state->uniforms[i]->v2.name, sect_size - 53);
- } else {
- clean_ascii(state->uniforms[i]->v1.name, sect_size - 41);
- }
-
- if (full_dump) {
- printf("######## UNIFORM: (size %d)\n", sect_size);
- dump_uniform(state->uniforms[i]);
- dump_hex((char *)state->uniforms[i], sect_size);
- }
- }
-
- for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
- state->samplers[i] = next_sect(state, &sect_size);
-
- /* hmm, for a3xx (or maybe just newer driver version), we have some
- * extra sections that don't seem useful, so skip these:
- */
- while (!valid_type(state->samplers[i]->type_info)) {
- dump_hex_ascii(state->samplers[i], sect_size, 0);
- state->samplers[i] = next_sect(state, &sect_size);
- }
-
- clean_ascii(state->samplers[i]->name, sect_size - 33);
- if (full_dump) {
- printf("######## SAMPLER: (size %d)\n", sect_size);
- dump_sampler(state->samplers[i]);
- dump_hex((char *)state->samplers[i], sect_size);
- }
-
- }
-
- // These sections show up after all of the other sampler sections
- // Loops through them all since we don't deal with them
- if (state->hdr->revision >= 7) {
- for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
- ptr = next_sect(state, &sect_size);
- dump_hex_ascii(ptr, sect_size, 0);
- }
- }
-
-
- for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) {
- state->varyings[i] = next_sect(state, &sect_size);
-
- /* hmm, for a3xx (or maybe just newer driver version), we have some
- * extra sections that don't seem useful, so skip these:
- */
- while (!valid_type(state->varyings[i]->type_info)) {
- dump_hex_ascii(state->varyings[i], sect_size, 0);
- state->varyings[i] = next_sect(state, &sect_size);
- }
-
- clean_ascii(state->varyings[i]->name, sect_size - 16);
- if (full_dump) {
- printf("######## VARYING: (size %d)\n", sect_size);
- dump_varying(state->varyings[i]);
- dump_hex((char *)state->varyings[i], sect_size);
- }
- }
-
- /* show up again for revision >= 14?? */
- if (state->hdr->revision >= 14) {
- for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) {
- ptr = next_sect(state, &sect_size);
- dump_hex_ascii(ptr, sect_size, 0);
- }
- }
-
- /* not sure exactly which revision started this, but seems at least
- * rev7 and rev8 implicitly include a new section for gl_FragColor:
- */
- if (state->hdr->revision >= 7) {
- /* I guess only one? */
- state->outputs[0] = next_sect(state, &sect_size);
-
- clean_ascii(state->outputs[0]->name, sect_size - 32);
- if (full_dump) {
- printf("######## OUTPUT: (size %d)\n", sect_size);
- dump_output(state->outputs[0]);
- dump_hex((char *)state->outputs[0], sect_size);
- }
- }
-
- for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) {
- state->uniformblocks[i].header = next_sect(state, &sect_size);
-
- clean_ascii(state->uniformblocks[i].header->name, sect_size - 40);
- if (full_dump) {
- printf("######## UNIFORM BLOCK: (size %d)\n", sect_size);
- dump_uniformblock(state->uniformblocks[i].header);
- dump_hex((char *)state->uniformblocks[i].header, sect_size);
- }
-
- /*
- * OpenGL ES 3.0 spec mandates a minimum amount of 16K members supported
- * a330 supports a minimum of 65K
- */
- state->uniformblocks[i].members = malloc(state->uniformblocks[i].header->num_members * sizeof(void*));
-
- int member = 0;
- for (member = 0; (member < state->uniformblocks[i].header->num_members) && (state->sz > 0); member++) {
- state->uniformblocks[i].members[member] = next_sect(state, &sect_size);
-
- clean_ascii(state->uniformblocks[i].members[member]->name, sect_size - 56);
- if (full_dump) {
- printf("######## UNIFORM BLOCK MEMBER: (size %d)\n", sect_size);
- dump_uniformblockmember(state->uniformblocks[i].members[member]);
- dump_hex((char *)state->uniformblocks[i].members[member], sect_size);
- }
- }
- /*
- * Qualcomm saves the UBO members twice for each UBO
- * Don't ask me why
- */
- for (member = 0; (member < state->uniformblocks[i].header->num_members) && (state->sz > 0); member++) {
- state->uniformblocks[i].members[member] = next_sect(state, &sect_size);
-
- clean_ascii(state->uniformblocks[i].members[member]->name, sect_size - 56);
- if (full_dump) {
- printf("######## UNIFORM BLOCK MEMBER2: (size %d)\n", sect_size);
- dump_uniformblockmember(state->uniformblocks[i].members[member]);
- dump_hex((char *)state->uniformblocks[i].members[member], sect_size);
- }
- }
- }
-
- if (gpu_id >= 300) {
- dump_shaders_a3xx(state);
- } else {
- dump_shaders_a2xx(state);
- }
-
- if (!full_dump)
- return;
-
- /* dump ascii version of shader program: */
- ptr = next_sect(state, &sect_size);
- printf("\n#######################################################\n");
- printf("######## SHADER SRC: (size=%d)\n", sect_size);
- dump_ascii(ptr, sect_size);
- free(ptr);
-
- /* dump remaining sections (there shouldn't be any): */
- while (state->sz > 0) {
- ptr = next_sect(state, &sect_size);
- printf("######## section (size=%d)\n", sect_size);
- printf("as hex:\n");
- dump_hex(ptr, sect_size);
- printf("as float:\n");
- dump_float(ptr, sect_size);
- printf("as ascii:\n");
- dump_ascii(ptr, sect_size);
- free(ptr);
- }
- /* cleanup the uniform buffer members we allocated */
- if (state->hdr->num_uniformblocks > 0)
- free (state->uniformblocks[i].members);
+ int i, sect_size;
+ uint8_t *ptr;
+
+ state->hdr = next_sect(state, &sect_size);
+
+ printf("######## HEADER: (size %d)\n", sect_size);
+ printf("\tsize: %d\n", state->hdr->size);
+ printf("\trevision: %d\n", state->hdr->revision);
+ printf("\tattributes: %d\n", state->hdr->num_attribs);
+ printf("\tuniforms: %d\n", state->hdr->num_uniforms);
+ printf("\tsamplers: %d\n", state->hdr->num_samplers);
+ printf("\tvaryings: %d\n", state->hdr->num_varyings);
+ printf("\tuniform blocks: %d\n", state->hdr->num_uniformblocks);
+ if (full_dump)
+ dump_hex((void *)state->hdr, sect_size);
+ printf("\n");
+
+ /* there seems to be two 0xba5eba11's at the end of the header, possibly
+ * with some other stuff between them:
+ */
+ ptr = next_sect(state, &sect_size);
+ if (full_dump) {
+ dump_hex_ascii(ptr, sect_size, 0);
+ }
+
+ for (i = 0; (i < state->hdr->num_attribs) && (state->sz > 0); i++) {
+ state->attribs[i] = next_sect(state, &sect_size);
+
+ /* hmm, for a3xx (or maybe just newer driver version), we have some
+ * extra sections that don't seem useful, so skip these:
+ */
+ while (!valid_type(state->attribs[i]->type_info)) {
+ dump_hex_ascii(state->attribs[i], sect_size, 0);
+ state->attribs[i] = next_sect(state, &sect_size);
+ }
+
+ clean_ascii(state->attribs[i]->name, sect_size - 28);
+ if (full_dump) {
+ printf("######## ATTRIBUTE: (size %d)\n", sect_size);
+ dump_attribute(state->attribs[i]);
+ dump_hex((char *)state->attribs[i], sect_size);
+ }
+ }
+
+ for (i = 0; (i < state->hdr->num_uniforms) && (state->sz > 0); i++) {
+ state->uniforms[i] = next_sect(state, &sect_size);
+
+ /* hmm, for a3xx (or maybe just newer driver version), we have some
+ * extra sections that don't seem useful, so skip these:
+ */
+ while (!valid_type(state->uniforms[i]->type_info)) {
+ dump_hex_ascii(state->uniforms[i], sect_size, 0);
+ state->uniforms[i] = next_sect(state, &sect_size);
+ }
+
+ if (is_uniform_v2(state->uniforms[i])) {
+ clean_ascii(state->uniforms[i]->v2.name, sect_size - 53);
+ } else {
+ clean_ascii(state->uniforms[i]->v1.name, sect_size - 41);
+ }
+
+ if (full_dump) {
+ printf("######## UNIFORM: (size %d)\n", sect_size);
+ dump_uniform(state->uniforms[i]);
+ dump_hex((char *)state->uniforms[i], sect_size);
+ }
+ }
+
+ for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
+ state->samplers[i] = next_sect(state, &sect_size);
+
+ /* hmm, for a3xx (or maybe just newer driver version), we have some
+ * extra sections that don't seem useful, so skip these:
+ */
+ while (!valid_type(state->samplers[i]->type_info)) {
+ dump_hex_ascii(state->samplers[i], sect_size, 0);
+ state->samplers[i] = next_sect(state, &sect_size);
+ }
+
+ clean_ascii(state->samplers[i]->name, sect_size - 33);
+ if (full_dump) {
+ printf("######## SAMPLER: (size %d)\n", sect_size);
+ dump_sampler(state->samplers[i]);
+ dump_hex((char *)state->samplers[i], sect_size);
+ }
+ }
+
+ // These sections show up after all of the other sampler sections
+ // Loops through them all since we don't deal with them
+ if (state->hdr->revision >= 7) {
+ for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
+ ptr = next_sect(state, &sect_size);
+ dump_hex_ascii(ptr, sect_size, 0);
+ }
+ }
+
+ for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) {
+ state->varyings[i] = next_sect(state, &sect_size);
+
+ /* hmm, for a3xx (or maybe just newer driver version), we have some
+ * extra sections that don't seem useful, so skip these:
+ */
+ while (!valid_type(state->varyings[i]->type_info)) {
+ dump_hex_ascii(state->varyings[i], sect_size, 0);
+ state->varyings[i] = next_sect(state, &sect_size);
+ }
+
+ clean_ascii(state->varyings[i]->name, sect_size - 16);
+ if (full_dump) {
+ printf("######## VARYING: (size %d)\n", sect_size);
+ dump_varying(state->varyings[i]);
+ dump_hex((char *)state->varyings[i], sect_size);
+ }
+ }
+
+ /* show up again for revision >= 14?? */
+ if (state->hdr->revision >= 14) {
+ for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) {
+ ptr = next_sect(state, &sect_size);
+ dump_hex_ascii(ptr, sect_size, 0);
+ }
+ }
+
+ /* not sure exactly which revision started this, but seems at least
+ * rev7 and rev8 implicitly include a new section for gl_FragColor:
+ */
+ if (state->hdr->revision >= 7) {
+ /* I guess only one? */
+ state->outputs[0] = next_sect(state, &sect_size);
+
+ clean_ascii(state->outputs[0]->name, sect_size - 32);
+ if (full_dump) {
+ printf("######## OUTPUT: (size %d)\n", sect_size);
+ dump_output(state->outputs[0]);
+ dump_hex((char *)state->outputs[0], sect_size);
+ }
+ }
+
+ for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) {
+ state->uniformblocks[i].header = next_sect(state, &sect_size);
+
+ clean_ascii(state->uniformblocks[i].header->name, sect_size - 40);
+ if (full_dump) {
+ printf("######## UNIFORM BLOCK: (size %d)\n", sect_size);
+ dump_uniformblock(state->uniformblocks[i].header);
+ dump_hex((char *)state->uniformblocks[i].header, sect_size);
+ }
+
+ /*
+ * OpenGL ES 3.0 spec mandates a minimum amount of 16K members supported
+ * a330 supports a minimum of 65K
+ */
+ state->uniformblocks[i].members =
+ malloc(state->uniformblocks[i].header->num_members * sizeof(void *));
+
+ int member = 0;
+ for (member = 0; (member < state->uniformblocks[i].header->num_members) &&
+ (state->sz > 0);
+ member++) {
+ state->uniformblocks[i].members[member] = next_sect(state, &sect_size);
+
+ clean_ascii(state->uniformblocks[i].members[member]->name,
+ sect_size - 56);
+ if (full_dump) {
+ printf("######## UNIFORM BLOCK MEMBER: (size %d)\n", sect_size);
+ dump_uniformblockmember(state->uniformblocks[i].members[member]);
+ dump_hex((char *)state->uniformblocks[i].members[member],
+ sect_size);
+ }
+ }
+ /*
+ * Qualcomm saves the UBO members twice for each UBO
+ * Don't ask me why
+ */
+ for (member = 0; (member < state->uniformblocks[i].header->num_members) &&
+ (state->sz > 0);
+ member++) {
+ state->uniformblocks[i].members[member] = next_sect(state, &sect_size);
+
+ clean_ascii(state->uniformblocks[i].members[member]->name,
+ sect_size - 56);
+ if (full_dump) {
+ printf("######## UNIFORM BLOCK MEMBER2: (size %d)\n", sect_size);
+ dump_uniformblockmember(state->uniformblocks[i].members[member]);
+ dump_hex((char *)state->uniformblocks[i].members[member],
+ sect_size);
+ }
+ }
+ }
+
+ if (gpu_id >= 300) {
+ dump_shaders_a3xx(state);
+ } else {
+ dump_shaders_a2xx(state);
+ }
+
+ if (!full_dump)
+ return;
+
+ /* dump ascii version of shader program: */
+ ptr = next_sect(state, &sect_size);
+ printf("\n#######################################################\n");
+ printf("######## SHADER SRC: (size=%d)\n", sect_size);
+ dump_ascii(ptr, sect_size);
+ free(ptr);
+
+ /* dump remaining sections (there shouldn't be any): */
+ while (state->sz > 0) {
+ ptr = next_sect(state, &sect_size);
+ printf("######## section (size=%d)\n", sect_size);
+ printf("as hex:\n");
+ dump_hex(ptr, sect_size);
+ printf("as float:\n");
+ dump_float(ptr, sect_size);
+ printf("as ascii:\n");
+ dump_ascii(ptr, sect_size);
+ free(ptr);
+ }
+ /* cleanup the uniform buffer members we allocated */
+ if (state->hdr->num_uniformblocks > 0)
+ free(state->uniformblocks[i].members);
}
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
- enum rd_sect_type type = RD_NONE;
- enum debug_t debug = PRINT_RAW | PRINT_STATS;
- void *buf = NULL;
- int sz;
- struct io *io;
- int raw_program = 0;
-
- /* lame argument parsing: */
-
- while (1) {
- if ((argc > 1) && !strcmp(argv[1], "--verbose")) {
- debug |= PRINT_RAW | PRINT_VERBOSE;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--expand")) {
- debug |= EXPAND_REPEAT;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--short")) {
- /* only short dump, original shader, symbol table, and disassembly */
- full_dump = 0;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--dump-shaders")) {
- dump_shaders = 1;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--raw")) {
- raw_program = 1;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--gpu300")) {
- gpu_id = 320;
- argv++;
- argc--;
- continue;
- }
- break;
- }
-
- if (argc != 2) {
- fprintf(stderr, "usage: pgmdump [--verbose] [--short] [--dump-shaders] testlog.rd\n");
- return -1;
- }
-
- disasm_a2xx_set_debug(debug);
- disasm_a3xx_set_debug(debug);
-
- infile = argv[1];
-
- io = io_open(infile);
- if (!io) {
- fprintf(stderr, "could not open: %s\n", infile);
- return -1;
- }
-
- if (raw_program)
- {
- io_readn(io, &sz, 4);
- free(buf);
-
- /* note: allow hex dumps to go a bit past the end of the buffer..
- * might see some garbage, but better than missing the last few bytes..
- */
- buf = calloc(1, sz + 3);
- io_readn(io, buf + 4, sz);
- (*(int*)buf) = sz;
-
- struct state state = {
- .buf = buf,
- .sz = sz,
- };
- printf("############################################################\n");
- printf("program:\n");
- dump_program(&state);
- printf("############################################################\n");
- return 0;
- }
-
- /* figure out what sort of input we are dealing with: */
- if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) {
- gl_shader_stage shader = ~0;
- int ret;
- if (check_extension(infile, ".vo")) {
- shader = MESA_SHADER_VERTEX;
- } else if (check_extension(infile, ".fo")) {
- shader = MESA_SHADER_FRAGMENT;
- } else if (check_extension(infile, ".vo3")) {
- } else if (check_extension(infile, ".fo3")) {
- } else if (check_extension(infile, ".co3")) {
- } else {
- fprintf(stderr, "invalid input file: %s\n", infile);
- return -1;
- }
- buf = calloc(1, 100 * 1024);
- ret = io_readn(io, buf, 100 * 1024);
- if (ret < 0) {
- fprintf(stderr, "error: %m");
- return -1;
- }
- if (shader != ~0) {
- return disasm_a2xx(buf, ret/4, 0, shader);
- } else {
- /* disassembly does not depend on shader stage on a3xx+: */
- return disasm_a3xx(buf, ret/4, 0, stdout, gpu_id);
- }
- }
-
- while ((io_readn(io, &type, sizeof(type)) > 0) && (io_readn(io, &sz, 4) > 0)) {
- free(buf);
-
- /* note: allow hex dumps to go a bit past the end of the buffer..
- * might see some garbage, but better than missing the last few bytes..
- */
- buf = calloc(1, sz + 3);
- io_readn(io, buf, sz);
-
- switch(type) {
- case RD_TEST:
- if (full_dump)
- printf("test: %s\n", (char *)buf);
- break;
- case RD_VERT_SHADER:
- printf("vertex shader:\n%s\n", (char *)buf);
- break;
- case RD_FRAG_SHADER:
- printf("fragment shader:\n%s\n", (char *)buf);
- break;
- case RD_PROGRAM: {
- struct state state = {
- .buf = buf,
- .sz = sz,
- };
- printf("############################################################\n");
- printf("program:\n");
- dump_program(&state);
- printf("############################################################\n");
- break;
- }
- case RD_GPU_ID:
- gpu_id = *((unsigned int *)buf);
- printf("gpu_id: %d\n", gpu_id);
- break;
- default:
- break;
- }
- }
-
- io_close(io);
-
- return 0;
+ enum rd_sect_type type = RD_NONE;
+ enum debug_t debug = PRINT_RAW | PRINT_STATS;
+ void *buf = NULL;
+ int sz;
+ struct io *io;
+ int raw_program = 0;
+
+ /* lame argument parsing: */
+
+ while (1) {
+ if ((argc > 1) && !strcmp(argv[1], "--verbose")) {
+ debug |= PRINT_RAW | PRINT_VERBOSE;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--expand")) {
+ debug |= EXPAND_REPEAT;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--short")) {
+ /* only short dump, original shader, symbol table, and disassembly */
+ full_dump = 0;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--dump-shaders")) {
+ dump_shaders = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--raw")) {
+ raw_program = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--gpu300")) {
+ gpu_id = 320;
+ argv++;
+ argc--;
+ continue;
+ }
+ break;
+ }
+
+ if (argc != 2) {
+ fprintf(
+ stderr,
+ "usage: pgmdump [--verbose] [--short] [--dump-shaders] testlog.rd\n");
+ return -1;
+ }
+
+ disasm_a2xx_set_debug(debug);
+ disasm_a3xx_set_debug(debug);
+
+ infile = argv[1];
+
+ io = io_open(infile);
+ if (!io) {
+ fprintf(stderr, "could not open: %s\n", infile);
+ return -1;
+ }
+
+ if (raw_program) {
+ io_readn(io, &sz, 4);
+ free(buf);
+
+ /* note: allow hex dumps to go a bit past the end of the buffer..
+ * might see some garbage, but better than missing the last few bytes..
+ */
+ buf = calloc(1, sz + 3);
+ io_readn(io, buf + 4, sz);
+ (*(int *)buf) = sz;
+
+ struct state state = {
+ .buf = buf,
+ .sz = sz,
+ };
+ printf("############################################################\n");
+ printf("program:\n");
+ dump_program(&state);
+ printf("############################################################\n");
+ return 0;
+ }
+
+ /* figure out what sort of input we are dealing with: */
+ if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) {
+ gl_shader_stage shader = ~0;
+ int ret;
+ if (check_extension(infile, ".vo")) {
+ shader = MESA_SHADER_VERTEX;
+ } else if (check_extension(infile, ".fo")) {
+ shader = MESA_SHADER_FRAGMENT;
+ } else if (check_extension(infile, ".vo3")) {
+ } else if (check_extension(infile, ".fo3")) {
+ } else if (check_extension(infile, ".co3")) {
+ } else {
+ fprintf(stderr, "invalid input file: %s\n", infile);
+ return -1;
+ }
+ buf = calloc(1, 100 * 1024);
+ ret = io_readn(io, buf, 100 * 1024);
+ if (ret < 0) {
+ fprintf(stderr, "error: %m");
+ return -1;
+ }
+ if (shader != ~0) {
+ return disasm_a2xx(buf, ret / 4, 0, shader);
+ } else {
+ /* disassembly does not depend on shader stage on a3xx+: */
+ return disasm_a3xx(buf, ret / 4, 0, stdout, gpu_id);
+ }
+ }
+
+ while ((io_readn(io, &type, sizeof(type)) > 0) &&
+ (io_readn(io, &sz, 4) > 0)) {
+ free(buf);
+
+ /* note: allow hex dumps to go a bit past the end of the buffer..
+ * might see some garbage, but better than missing the last few bytes..
+ */
+ buf = calloc(1, sz + 3);
+ io_readn(io, buf, sz);
+
+ switch (type) {
+ case RD_TEST:
+ if (full_dump)
+ printf("test: %s\n", (char *)buf);
+ break;
+ case RD_VERT_SHADER:
+ printf("vertex shader:\n%s\n", (char *)buf);
+ break;
+ case RD_FRAG_SHADER:
+ printf("fragment shader:\n%s\n", (char *)buf);
+ break;
+ case RD_PROGRAM: {
+ struct state state = {
+ .buf = buf,
+ .sz = sz,
+ };
+ printf(
+ "############################################################\n");
+ printf("program:\n");
+ dump_program(&state);
+ printf(
+ "############################################################\n");
+ break;
+ }
+ case RD_GPU_ID:
+ gpu_id = *((unsigned int *)buf);
+ printf("gpu_id: %d\n", gpu_id);
+ break;
+ default:
+ break;
+ }
+ }
+
+ io_close(io);
+
+ return 0;
}
-
diff --git a/src/freedreno/decode/pgmdump2.c b/src/freedreno/decode/pgmdump2.c
index 94db08db503..227fd22c131 100644
--- a/src/freedreno/decode/pgmdump2.c
+++ b/src/freedreno/decode/pgmdump2.c
@@ -36,550 +36,569 @@
#include <assert.h>
#include <ctype.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <stddef.h>
-#include <fcntl.h>
-#include <string.h>
+#include <sys/types.h>
-#include "redump.h"
#include "disasm.h"
#include "io.h"
+#include "redump.h"
#include "util.h"
const char *infile;
static int dump_full = 0;
static int dump_offsets = 0;
static int gpu_id = 320;
-static int shaderdb = 0; /* output shaderdb style traces to stderr */
+static int shaderdb = 0; /* output shaderdb style traces to stderr */
struct state {
- char *buf;
- int sz;
- int lvl;
+ char *buf;
+ int sz;
+ int lvl;
- /* current shader_info section, some offsets calculated relative to
- * this, rather than relative to start of buffer.
- */
- void *shader;
+ /* current shader_info section, some offsets calculated relative to
+ * this, rather than relative to start of buffer.
+ */
+ void *shader;
- /* size of each entry within a shader_descriptor_blk: */
- int desc_size;
+ /* size of each entry within a shader_descriptor_blk: */
+ int desc_size;
- const char *shader_type;
- int full_regs;
- int half_regs;
+ const char *shader_type;
+ int full_regs;
+ int half_regs;
};
#define PACKED __attribute__((__packed__))
-#define OFF(field) do { \
- if (dump_offsets) \
- printf("%08x: ", (uint32_t)((char *)&field - state->buf));\
- } while (0)
+#define OFF(field) \
+ do { \
+ if (dump_offsets) \
+ printf("%08x: ", (uint32_t)((char *)&field - state->buf)); \
+ } while (0)
/* decode field as hex */
-#define X(s, field) do { \
- OFF(s->field); \
- printf("%s%12s:\t0x%x\n", tab(state->lvl), #field, s->field); \
- } while (0)
+#define X(s, field) \
+ do { \
+ OFF(s->field); \
+ printf("%s%12s:\t0x%x\n", tab(state->lvl), #field, s->field); \
+ } while (0)
/* decode field as digit */
-#define D(s, field) do { \
- OFF(s->field); \
- printf("%s%12s:\t%u\n", tab(state->lvl), #field, s->field); \
- } while (0)
+#define D(s, field) \
+ do { \
+ OFF(s->field); \
+ printf("%s%12s:\t%u\n", tab(state->lvl), #field, s->field); \
+ } while (0)
/* decode field as float/hex */
-#define F(s, field) do { \
- OFF(s->field); \
- printf("%s%12s:\t%f (0x%0x)\n", tab(state->lvl), #field, \
- d2f(s->field), s->field); \
- } while (0)
+#define F(s, field) \
+ do { \
+ OFF(s->field); \
+ printf("%s%12s:\t%f (0x%0x)\n", tab(state->lvl), #field, d2f(s->field), \
+ s->field); \
+ } while (0)
/* decode field as register: (type is 'r' or 'c') */
-#define R(s, field, type) do { \
- OFF(s->field); \
- printf("%s%12s:\t%c%u.%c\n", tab(state->lvl), #field, type, \
- (s->field >> 2), "xyzw"[s->field & 0x3]); \
- } while (0)
+#define R(s, field, type) \
+ do { \
+ OFF(s->field); \
+ printf("%s%12s:\t%c%u.%c\n", tab(state->lvl), #field, type, \
+ (s->field >> 2), "xyzw"[s->field & 0x3]); \
+ } while (0)
/* decode inline string (presumably null terminated?) */
-#define S(s, field) do { \
- OFF(s->field); \
- printf("%s%12s:\t%s\n", tab(state->lvl), #field, s->field); \
- } while (0)
+#define S(s, field) \
+ do { \
+ OFF(s->field); \
+ printf("%s%12s:\t%s\n", tab(state->lvl), #field, s->field); \
+ } while (0)
/* decode string-table string */
-#define T(s, field) TODO
+#define T(s, field) TODO
/* decode field as unknown */
-#define U(s, start, end) \
- dump_unknown(state, s->unk_ ## start ## _ ## end, 0x ## start, (4 + 0x ## end - 0x ## start) / 4)
+#define U(s, start, end) \
+ dump_unknown(state, s->unk_##start##_##end, 0x##start, \
+ (4 + 0x##end - 0x##start) / 4)
/* decode field as offset to other section */
-#define O(s, field, type) do { \
- X(s, field); \
- assert(s->field < state->sz); \
- void *_p = &state->buf[s->field]; \
- state->lvl++; \
- decode_ ## type (state, _p); \
- state->lvl--; \
- } while (0)
+#define O(s, field, type) \
+ do { \
+ X(s, field); \
+ assert(s->field < state->sz); \
+ void *_p = &state->buf[s->field]; \
+ state->lvl++; \
+ decode_##type(state, _p); \
+ state->lvl--; \
+ } while (0)
struct shader_info;
static void decode_shader_info(struct state *state, struct shader_info *info);
-static void dump_unknown(struct state *state, void *buf, unsigned start, unsigned n)
+static void
+dump_unknown(struct state *state, void *buf, unsigned start, unsigned n)
{
- uint32_t *ptr = buf;
- uint8_t *ascii = buf;
-
- for (unsigned i = 0; i < n; i++) {
- uint32_t d = ptr[i];
-
- if (dump_offsets)
- printf("%08x:", (uint32_t)((char *)&ptr[i] - state->buf));
-
- printf("%s %04x:\t%08x", tab(state->lvl), start + i * 4, d);
-
- printf("\t|");
- for (unsigned j = 0; j < 4; j++) {
- uint8_t c = *(ascii++);
- printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
- }
- printf("|\t%f", d2f(d));
-
- /* TODO maybe scan for first non-null and non-ascii char starting from
- * end of shader binary to (roughly) establish the start of the string
- * table.. that would be a bit better filter for deciding if something
- * might be a pointer into the string table. Also, the previous char
- * to what it points to should probably be null.
- */
- if ((d < state->sz) &&
- isascii(state->buf[d]) &&
- (strlen(&state->buf[d]) > 2) &&
- isascii(state->buf[d+1]))
- printf("\t<== %s", &state->buf[d]);
-
- printf("\n");
- }
+ uint32_t *ptr = buf;
+ uint8_t *ascii = buf;
+
+ for (unsigned i = 0; i < n; i++) {
+ uint32_t d = ptr[i];
+
+ if (dump_offsets)
+ printf("%08x:", (uint32_t)((char *)&ptr[i] - state->buf));
+
+ printf("%s %04x:\t%08x", tab(state->lvl), start + i * 4, d);
+
+ printf("\t|");
+ for (unsigned j = 0; j < 4; j++) {
+ uint8_t c = *(ascii++);
+ printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
+ }
+ printf("|\t%f", d2f(d));
+
+ /* TODO maybe scan for first non-null and non-ascii char starting from
+ * end of shader binary to (roughly) establish the start of the string
+ * table.. that would be a bit better filter for deciding if something
+ * might be a pointer into the string table. Also, the previous char
+ * to what it points to should probably be null.
+ */
+ if ((d < state->sz) && isascii(state->buf[d]) &&
+ (strlen(&state->buf[d]) > 2) && isascii(state->buf[d + 1]))
+ printf("\t<== %s", &state->buf[d]);
+
+ printf("\n");
+ }
}
struct PACKED header {
- uint32_t version; /* I guess, always b10bcace ? */
- uint32_t unk_0004_0014[5];
- uint32_t size;
- uint32_t size2; /* just to be sure? */
- uint32_t unk_0020_0020[1];
- uint32_t chksum; /* I guess? Small changes seem to result in big diffs here */
- uint32_t unk_0028_0050[11];
- uint32_t fs_info; /* offset of FS shader_info section */
- uint32_t unk_0058_0090[15];
- uint32_t vs_info; /* offset of VS shader_info section */
- uint32_t unk_0098_00b0[7];
- uint32_t vs_info2; /* offset of VS shader_info section (again?) */
- uint32_t unk_00b8_0110[23];
- uint32_t bs_info; /* offset of binning shader_info section */
+ uint32_t version; /* I guess, always b10bcace ? */
+ uint32_t unk_0004_0014[5];
+ uint32_t size;
+ uint32_t size2; /* just to be sure? */
+ uint32_t unk_0020_0020[1];
+ uint32_t
+ chksum; /* I guess? Small changes seem to result in big diffs here */
+ uint32_t unk_0028_0050[11];
+ uint32_t fs_info; /* offset of FS shader_info section */
+ uint32_t unk_0058_0090[15];
+ uint32_t vs_info; /* offset of VS shader_info section */
+ uint32_t unk_0098_00b0[7];
+ uint32_t vs_info2; /* offset of VS shader_info section (again?) */
+ uint32_t unk_00b8_0110[23];
+ uint32_t bs_info; /* offset of binning shader_info section */
};
-static void decode_header(struct state *state, struct header *hdr)
+static void
+decode_header(struct state *state, struct header *hdr)
{
- X(hdr, version);
- U(hdr, 0004, 0014);
- X(hdr, size);
- X(hdr, size2);
- U(hdr, 0020, 0020);
- X(hdr, chksum);
- U(hdr, 0028, 0050);
- state->shader_type = "FRAG";
- O(hdr, fs_info, shader_info);
- U(hdr, 0058, 0090);
- state->shader_type = "VERT";
- O(hdr, vs_info, shader_info);
- U(hdr, 0098, 00b0);
- assert(hdr->vs_info == hdr->vs_info2); /* not sure what this if it is ever different */
- X(hdr, vs_info2);
- U(hdr, 00b8, 0110);
- state->shader_type = "BVERT";
- O(hdr, bs_info, shader_info);
-
- /* not sure how much of the rest of contents before start of fs_info
- * is the header, vs other things.. just dump it all as unknown for
- * now:
- */
- dump_unknown(state, (void *)hdr + sizeof(*hdr),
- sizeof(*hdr), (hdr->fs_info - sizeof(*hdr)) / 4);
+ X(hdr, version);
+ U(hdr, 0004, 0014);
+ X(hdr, size);
+ X(hdr, size2);
+ U(hdr, 0020, 0020);
+ X(hdr, chksum);
+ U(hdr, 0028, 0050);
+ state->shader_type = "FRAG";
+ O(hdr, fs_info, shader_info);
+ U(hdr, 0058, 0090);
+ state->shader_type = "VERT";
+ O(hdr, vs_info, shader_info);
+ U(hdr, 0098, 00b0);
+ assert(hdr->vs_info ==
+ hdr->vs_info2); /* not sure what this if it is ever different */
+ X(hdr, vs_info2);
+ U(hdr, 00b8, 0110);
+ state->shader_type = "BVERT";
+ O(hdr, bs_info, shader_info);
+
+ /* not sure how much of the rest of contents before start of fs_info
+ * is the header, vs other things.. just dump it all as unknown for
+ * now:
+ */
+ dump_unknown(state, (void *)hdr + sizeof(*hdr), sizeof(*hdr),
+ (hdr->fs_info - sizeof(*hdr)) / 4);
}
struct PACKED shader_entry_point {
- /* entry point name, ie. "main" of TBD length, followed by unknown */
- char name[8];
+ /* entry point name, ie. "main" of TBD length, followed by unknown */
+ char name[8];
};
-static void decode_shader_entry_point(struct state *state,
- struct shader_entry_point *e)
+static void
+decode_shader_entry_point(struct state *state, struct shader_entry_point *e)
{
- S(e, name);
+ S(e, name);
}
struct PACKED shader_config {
- uint32_t unk_0000_0008[3];
- uint32_t full_regs;
- uint32_t half_regs;
+ uint32_t unk_0000_0008[3];
+ uint32_t full_regs;
+ uint32_t half_regs;
};
-static void decode_shader_config(struct state *state, struct shader_config *cfg)
+static void
+decode_shader_config(struct state *state, struct shader_config *cfg)
{
- U(cfg, 0000, 0008);
- D(cfg, full_regs);
- D(cfg, half_regs);
+ U(cfg, 0000, 0008);
+ D(cfg, full_regs);
+ D(cfg, half_regs);
- state->full_regs = cfg->full_regs;
- state->half_regs = cfg->half_regs;
+ state->full_regs = cfg->full_regs;
+ state->half_regs = cfg->half_regs;
- /* dump reset of unknown (size differs btwn versions) */
- dump_unknown(state, (void *)cfg + sizeof(*cfg), sizeof(*cfg),
- (state->desc_size - sizeof(*cfg))/4);
+ /* dump reset of unknown (size differs btwn versions) */
+ dump_unknown(state, (void *)cfg + sizeof(*cfg), sizeof(*cfg),
+ (state->desc_size - sizeof(*cfg)) / 4);
}
struct PACKED shader_io_block {
- /* name of TBD length followed by unknown.. 42 dwords total */
- char name[20];
- uint32_t unk_0014_00a4[37];
+ /* name of TBD length followed by unknown.. 42 dwords total */
+ char name[20];
+ uint32_t unk_0014_00a4[37];
};
-static void decode_shader_io_block(struct state *state,
- struct shader_io_block *io)
+static void
+decode_shader_io_block(struct state *state, struct shader_io_block *io)
{
- S(io, name);
- U(io, 0014, 00a4);
+ S(io, name);
+ U(io, 0014, 00a4);
}
struct PACKED shader_constant_block {
- uint32_t value;
- uint32_t unk_0004_000c[3];
- uint32_t regid;
- uint32_t unk_0014_0024[5];
+ uint32_t value;
+ uint32_t unk_0004_000c[3];
+ uint32_t regid;
+ uint32_t unk_0014_0024[5];
};
-static void decode_shader_constant_block(struct state *state,
- struct shader_constant_block *c)
+static void
+decode_shader_constant_block(struct state *state,
+ struct shader_constant_block *c)
{
- F(c, value);
- U(c, 0004, 000c);
- R(c, regid, 'c');
- U(c, 0014, 0024);
+ F(c, value);
+ U(c, 0004, 000c);
+ R(c, regid, 'c');
+ U(c, 0014, 0024);
}
enum {
- ENTRY_POINT = 0, /* shader_entry_point */
- SHADER_CONFIG = 1, /* XXX placeholder name */
- SHADER_INPUT = 2, /* shader_io_block */
- SHADER_OUTPUT = 3, /* shader_io_block */
- CONSTANTS = 6, /* shader_constant_block */
- INTERNAL = 8, /* internal input, like bary.f coord */
- SHADER = 10,
+ ENTRY_POINT = 0, /* shader_entry_point */
+ SHADER_CONFIG = 1, /* XXX placeholder name */
+ SHADER_INPUT = 2, /* shader_io_block */
+ SHADER_OUTPUT = 3, /* shader_io_block */
+ CONSTANTS = 6, /* shader_constant_block */
+ INTERNAL = 8, /* internal input, like bary.f coord */
+ SHADER = 10,
} shader_info_block_type;
/* Refers to location of some type of records, with an offset relative to
* start of shader_info block.
*/
struct PACKED shader_descriptor_block {
- uint32_t type; /* block type */
- uint32_t offset; /* offset (relative to start of shader_info block) */
- uint32_t size; /* size in bytes */
- uint32_t count; /* number of records */
- uint32_t unk_0010_0010[1];
+ uint32_t type; /* block type */
+ uint32_t offset; /* offset (relative to start of shader_info block) */
+ uint32_t size; /* size in bytes */
+ uint32_t count; /* number of records */
+ uint32_t unk_0010_0010[1];
};
-static void decode_shader_descriptor_block(struct state *state,
- struct shader_descriptor_block *blk)
+static void
+decode_shader_descriptor_block(struct state *state,
+ struct shader_descriptor_block *blk)
{
- D(blk, type);
- X(blk, offset);
- D(blk, size);
- D(blk, count);
- U(blk, 0010, 0010);
-
- /* offset relative to current shader block: */
- void *ptr = state->shader + blk->offset;
-
- if (blk->count == 0) {
- assert(blk->size == 0);
- } else {
- assert((blk->size % blk->count) == 0);
- }
-
- state->desc_size = blk->size / blk->count;
- state->lvl++;
- for (unsigned i = 0; i < blk->count; i++) {
- switch (blk->type) {
- case ENTRY_POINT:
- printf("%sentry point %u:\n", tab(state->lvl-1), i);
- decode_shader_entry_point(state, ptr);
- break;
- case SHADER_CONFIG:
- printf("%sconfig %u:\n", tab(state->lvl-1), i);
- decode_shader_config(state, ptr);
- break;
- case SHADER_INPUT:
- printf("%sinput %u:\n", tab(state->lvl-1), i);
- decode_shader_io_block(state, ptr);
- break;
- case SHADER_OUTPUT:
- printf("%soutput %u:\n", tab(state->lvl-1), i);
- decode_shader_io_block(state, ptr);
- break;
- case INTERNAL:
- printf("%sinternal input %u:\n", tab(state->lvl-1), i);
- decode_shader_io_block(state, ptr);
- break;
- case CONSTANTS:
- printf("%sconstant %u:\n", tab(state->lvl-1), i);
- decode_shader_constant_block(state, ptr);
- break;
- case SHADER: {
- struct shader_stats stats;
- printf("%sshader %u:\n", tab(state->lvl-1), i);
- disasm_a3xx_stat(ptr, blk->size/4, state->lvl, stdout, gpu_id, &stats);
- if (shaderdb) {
- unsigned dwords = 2 * stats.instlen;
-
- if (gpu_id >= 400) {
- dwords = ALIGN(dwords, 16 * 2);
- } else {
- dwords = ALIGN(dwords, 4 * 2);
- }
-
- unsigned half_regs = state->half_regs;
- unsigned full_regs = state->full_regs;
-
- /* On a6xx w/ merged/conflicting half and full regs, the
- * full_regs footprint will be max of full_regs and half
- * of half_regs.. we only care about which value is higher.
- */
- if (gpu_id >= 600) {
- /* footprint of half_regs in units of full_regs: */
- unsigned half_full = (half_regs + 1) / 2;
- if (half_full > full_regs)
- full_regs = half_full;
- half_regs = 0;
- }
-
- fprintf(stderr,
- "%s shader: %u inst, %u nops, %u non-nops, %u dwords, "
- "%u half, %u full, %u constlen, "
- "%u (ss), %u (sy), %d max_sun, %d loops\n",
- state->shader_type, stats.instructions,
- stats.nops, stats.instructions - stats.nops,
- dwords, half_regs, full_regs,
- stats.constlen, stats.ss, stats.sy,
- 0, 0); /* max_sun or loops not possible */
- }
- /* this is a special case in a way, blk->count is # of
- * instructions but disasm_a3xx() decodes all instructions,
- * so just bail.
- */
- i = blk->count;
- break;
- }
- default:
- dump_unknown(state, ptr, 0, state->desc_size/4);
- break;
- }
- ptr += state->desc_size;
- }
- state->lvl--;
+ D(blk, type);
+ X(blk, offset);
+ D(blk, size);
+ D(blk, count);
+ U(blk, 0010, 0010);
+
+ /* offset relative to current shader block: */
+ void *ptr = state->shader + blk->offset;
+
+ if (blk->count == 0) {
+ assert(blk->size == 0);
+ } else {
+ assert((blk->size % blk->count) == 0);
+ }
+
+ state->desc_size = blk->size / blk->count;
+ state->lvl++;
+ for (unsigned i = 0; i < blk->count; i++) {
+ switch (blk->type) {
+ case ENTRY_POINT:
+ printf("%sentry point %u:\n", tab(state->lvl - 1), i);
+ decode_shader_entry_point(state, ptr);
+ break;
+ case SHADER_CONFIG:
+ printf("%sconfig %u:\n", tab(state->lvl - 1), i);
+ decode_shader_config(state, ptr);
+ break;
+ case SHADER_INPUT:
+ printf("%sinput %u:\n", tab(state->lvl - 1), i);
+ decode_shader_io_block(state, ptr);
+ break;
+ case SHADER_OUTPUT:
+ printf("%soutput %u:\n", tab(state->lvl - 1), i);
+ decode_shader_io_block(state, ptr);
+ break;
+ case INTERNAL:
+ printf("%sinternal input %u:\n", tab(state->lvl - 1), i);
+ decode_shader_io_block(state, ptr);
+ break;
+ case CONSTANTS:
+ printf("%sconstant %u:\n", tab(state->lvl - 1), i);
+ decode_shader_constant_block(state, ptr);
+ break;
+ case SHADER: {
+ struct shader_stats stats;
+ printf("%sshader %u:\n", tab(state->lvl - 1), i);
+ disasm_a3xx_stat(ptr, blk->size / 4, state->lvl, stdout, gpu_id,
+ &stats);
+ if (shaderdb) {
+ unsigned dwords = 2 * stats.instlen;
+
+ if (gpu_id >= 400) {
+ dwords = ALIGN(dwords, 16 * 2);
+ } else {
+ dwords = ALIGN(dwords, 4 * 2);
+ }
+
+ unsigned half_regs = state->half_regs;
+ unsigned full_regs = state->full_regs;
+
+ /* On a6xx w/ merged/conflicting half and full regs, the
+ * full_regs footprint will be max of full_regs and half
+ * of half_regs.. we only care about which value is higher.
+ */
+ if (gpu_id >= 600) {
+ /* footprint of half_regs in units of full_regs: */
+ unsigned half_full = (half_regs + 1) / 2;
+ if (half_full > full_regs)
+ full_regs = half_full;
+ half_regs = 0;
+ }
+
+ fprintf(stderr,
+ "%s shader: %u inst, %u nops, %u non-nops, %u dwords, "
+ "%u half, %u full, %u constlen, "
+ "%u (ss), %u (sy), %d max_sun, %d loops\n",
+ state->shader_type, stats.instructions, stats.nops,
+ stats.instructions - stats.nops, dwords, half_regs,
+ full_regs, stats.constlen, stats.ss, stats.sy, 0,
+ 0); /* max_sun or loops not possible */
+ }
+ /* this is a special case in a way, blk->count is # of
+ * instructions but disasm_a3xx() decodes all instructions,
+ * so just bail.
+ */
+ i = blk->count;
+ break;
+ }
+ default:
+ dump_unknown(state, ptr, 0, state->desc_size / 4);
+ break;
+ }
+ ptr += state->desc_size;
+ }
+ state->lvl--;
}
/* there looks like one of these per shader, followed by "main" and
* some more info, and then the shader itself.
*/
struct PACKED shader_info {
- uint32_t unk_0000_0010[5];
- uint32_t desc_off; /* offset to first descriptor block */
- uint32_t num_blocks;
+ uint32_t unk_0000_0010[5];
+ uint32_t desc_off; /* offset to first descriptor block */
+ uint32_t num_blocks;
};
-static void decode_shader_info(struct state *state, struct shader_info *info)
+static void
+decode_shader_info(struct state *state, struct shader_info *info)
{
- assert((info->desc_off % 4) == 0);
+ assert((info->desc_off % 4) == 0);
- U(info, 0000, 0010);
- X(info, desc_off);
- D(info, num_blocks);
+ U(info, 0000, 0010);
+ X(info, desc_off);
+ D(info, num_blocks);
- dump_unknown(state, &info[1], 0, (info->desc_off - sizeof(*info))/4);
+ dump_unknown(state, &info[1], 0, (info->desc_off - sizeof(*info)) / 4);
- state->shader = info;
+ state->shader = info;
- struct shader_descriptor_block *blocks = ((void *)info) + info->desc_off;
- for (unsigned i = 0; i < info->num_blocks; i++) {
- printf("%sdescriptor %u:\n", tab(state->lvl), i);
- state->lvl++;
- decode_shader_descriptor_block(state, &blocks[i]);
- state->lvl--;
- }
+ struct shader_descriptor_block *blocks = ((void *)info) + info->desc_off;
+ for (unsigned i = 0; i < info->num_blocks; i++) {
+ printf("%sdescriptor %u:\n", tab(state->lvl), i);
+ state->lvl++;
+ decode_shader_descriptor_block(state, &blocks[i]);
+ state->lvl--;
+ }
}
-static void dump_program(struct state *state)
+static void
+dump_program(struct state *state)
{
- struct header *hdr = (void *)state->buf;
+ struct header *hdr = (void *)state->buf;
- if (dump_full)
- dump_unknown(state, state->buf, 0, state->sz/4);
+ if (dump_full)
+ dump_unknown(state, state->buf, 0, state->sz / 4);
- decode_header(state, hdr);
+ decode_header(state, hdr);
}
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
{
- enum rd_sect_type type = RD_NONE;
- enum debug_t debug = PRINT_RAW | PRINT_STATS;
- void *buf = NULL;
- int sz;
- struct io *io;
- int raw_program = 0;
-
- /* lame argument parsing: */
-
- while (1) {
- if ((argc > 1) && !strcmp(argv[1], "--verbose")) {
- debug |= PRINT_RAW | PRINT_VERBOSE;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--expand")) {
- debug |= EXPAND_REPEAT;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--full")) {
- /* only short dump, original shader, symbol table, and disassembly */
- dump_full = 1;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--dump-offsets")) {
- dump_offsets = 1;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--raw")) {
- raw_program = 1;
- argv++;
- argc--;
- continue;
- }
- if ((argc > 1) && !strcmp(argv[1], "--shaderdb")) {
- shaderdb = 1;
- argv++;
- argc--;
- continue;
- }
- break;
- }
-
- if (argc != 2) {
- fprintf(stderr, "usage: pgmdump2 [--verbose] [--expand] [--full] [--dump-offsets] [--raw] [--shaderdb] testlog.rd\n");
- return -1;
- }
-
- disasm_a3xx_set_debug(debug);
-
- infile = argv[1];
-
- io = io_open(infile);
- if (!io) {
- fprintf(stderr, "could not open: %s\n", infile);
- return -1;
- }
-
- if (raw_program)
- {
- io_readn(io, &sz, 4);
- free(buf);
-
- /* note: allow hex dumps to go a bit past the end of the buffer..
- * might see some garbage, but better than missing the last few bytes..
- */
- buf = calloc(1, sz + 3);
- io_readn(io, buf + 4, sz);
- (*(int*)buf) = sz;
-
- struct state state = {
- .buf = buf,
- .sz = sz,
- };
- printf("############################################################\n");
- printf("program:\n");
- dump_program(&state);
- printf("############################################################\n");
- return 0;
- }
-
- /* figure out what sort of input we are dealing with: */
- if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) {
- int ret;
- buf = calloc(1, 100 * 1024);
- ret = io_readn(io, buf, 100 * 1024);
- if (ret < 0) {
- fprintf(stderr, "error: %m");
- return -1;
- }
- return disasm_a3xx(buf, ret/4, 0, stdout, gpu_id);
- }
-
- while ((io_readn(io, &type, sizeof(type)) > 0) && (io_readn(io, &sz, 4) > 0)) {
- free(buf);
-
- /* note: allow hex dumps to go a bit past the end of the buffer..
- * might see some garbage, but better than missing the last few bytes..
- */
- buf = calloc(1, sz + 3);
- io_readn(io, buf, sz);
-
- switch(type) {
- case RD_TEST:
- if (dump_full)
- printf("test: %s\n", (char *)buf);
- break;
- case RD_VERT_SHADER:
- printf("vertex shader:\n%s\n", (char *)buf);
- break;
- case RD_FRAG_SHADER:
- printf("fragment shader:\n%s\n", (char *)buf);
- break;
- case RD_PROGRAM: {
- struct state state = {
- .buf = buf,
- .sz = sz,
- };
- printf("############################################################\n");
- printf("program:\n");
- dump_program(&state);
- printf("############################################################\n");
- break;
- }
- case RD_GPU_ID:
- gpu_id = *((unsigned int *)buf);
- printf("gpu_id: %d\n", gpu_id);
- break;
- default:
- break;
- }
- }
-
- io_close(io);
-
- return 0;
+ enum rd_sect_type type = RD_NONE;
+ enum debug_t debug = PRINT_RAW | PRINT_STATS;
+ void *buf = NULL;
+ int sz;
+ struct io *io;
+ int raw_program = 0;
+
+ /* lame argument parsing: */
+
+ while (1) {
+ if ((argc > 1) && !strcmp(argv[1], "--verbose")) {
+ debug |= PRINT_RAW | PRINT_VERBOSE;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--expand")) {
+ debug |= EXPAND_REPEAT;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--full")) {
+ /* only short dump, original shader, symbol table, and disassembly */
+ dump_full = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--dump-offsets")) {
+ dump_offsets = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--raw")) {
+ raw_program = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ if ((argc > 1) && !strcmp(argv[1], "--shaderdb")) {
+ shaderdb = 1;
+ argv++;
+ argc--;
+ continue;
+ }
+ break;
+ }
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: pgmdump2 [--verbose] [--expand] [--full] "
+ "[--dump-offsets] [--raw] [--shaderdb] testlog.rd\n");
+ return -1;
+ }
+
+ disasm_a3xx_set_debug(debug);
+
+ infile = argv[1];
+
+ io = io_open(infile);
+ if (!io) {
+ fprintf(stderr, "could not open: %s\n", infile);
+ return -1;
+ }
+
+ if (raw_program) {
+ io_readn(io, &sz, 4);
+ free(buf);
+
+ /* note: allow hex dumps to go a bit past the end of the buffer..
+ * might see some garbage, but better than missing the last few bytes..
+ */
+ buf = calloc(1, sz + 3);
+ io_readn(io, buf + 4, sz);
+ (*(int *)buf) = sz;
+
+ struct state state = {
+ .buf = buf,
+ .sz = sz,
+ };
+ printf("############################################################\n");
+ printf("program:\n");
+ dump_program(&state);
+ printf("############################################################\n");
+ return 0;
+ }
+
+ /* figure out what sort of input we are dealing with: */
+ if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) {
+ int ret;
+ buf = calloc(1, 100 * 1024);
+ ret = io_readn(io, buf, 100 * 1024);
+ if (ret < 0) {
+ fprintf(stderr, "error: %m");
+ return -1;
+ }
+ return disasm_a3xx(buf, ret / 4, 0, stdout, gpu_id);
+ }
+
+ while ((io_readn(io, &type, sizeof(type)) > 0) &&
+ (io_readn(io, &sz, 4) > 0)) {
+ free(buf);
+
+ /* note: allow hex dumps to go a bit past the end of the buffer..
+ * might see some garbage, but better than missing the last few bytes..
+ */
+ buf = calloc(1, sz + 3);
+ io_readn(io, buf, sz);
+
+ switch (type) {
+ case RD_TEST:
+ if (dump_full)
+ printf("test: %s\n", (char *)buf);
+ break;
+ case RD_VERT_SHADER:
+ printf("vertex shader:\n%s\n", (char *)buf);
+ break;
+ case RD_FRAG_SHADER:
+ printf("fragment shader:\n%s\n", (char *)buf);
+ break;
+ case RD_PROGRAM: {
+ struct state state = {
+ .buf = buf,
+ .sz = sz,
+ };
+ printf(
+ "############################################################\n");
+ printf("program:\n");
+ dump_program(&state);
+ printf(
+ "############################################################\n");
+ break;
+ }
+ case RD_GPU_ID:
+ gpu_id = *((unsigned int *)buf);
+ printf("gpu_id: %d\n", gpu_id);
+ break;
+ default:
+ break;
+ }
+ }
+
+ io_close(io);
+
+ return 0;
}
diff --git a/src/freedreno/decode/redump.h b/src/freedreno/decode/redump.h
index 1b5d3e1af51..c7121e8650d 100644
--- a/src/freedreno/decode/redump.h
+++ b/src/freedreno/decode/redump.h
@@ -25,52 +25,65 @@
#define REDUMP_H_
enum rd_sect_type {
- RD_NONE,
- RD_TEST, /* ascii text */
- RD_CMD, /* ascii text */
- RD_GPUADDR, /* u32 gpuaddr, u32 size */
- RD_CONTEXT, /* raw dump */
- RD_CMDSTREAM, /* raw dump */
- RD_CMDSTREAM_ADDR, /* gpu addr of cmdstream */
- RD_PARAM, /* u32 param_type, u32 param_val, u32 bitlen */
- RD_FLUSH, /* empty, clear previous params */
- RD_PROGRAM, /* shader program, raw dump */
- RD_VERT_SHADER,
- RD_FRAG_SHADER,
- RD_BUFFER_CONTENTS,
- RD_GPU_ID,
+ RD_NONE,
+ RD_TEST, /* ascii text */
+ RD_CMD, /* ascii text */
+ RD_GPUADDR, /* u32 gpuaddr, u32 size */
+ RD_CONTEXT, /* raw dump */
+ RD_CMDSTREAM, /* raw dump */
+ RD_CMDSTREAM_ADDR, /* gpu addr of cmdstream */
+ RD_PARAM, /* u32 param_type, u32 param_val, u32 bitlen */
+ RD_FLUSH, /* empty, clear previous params */
+ RD_PROGRAM, /* shader program, raw dump */
+ RD_VERT_SHADER,
+ RD_FRAG_SHADER,
+ RD_BUFFER_CONTENTS,
+ RD_GPU_ID,
};
/* RD_PARAM types: */
enum rd_param_type {
- RD_PARAM_SURFACE_WIDTH,
- RD_PARAM_SURFACE_HEIGHT,
- RD_PARAM_SURFACE_PITCH,
- RD_PARAM_COLOR,
- RD_PARAM_BLIT_X,
- RD_PARAM_BLIT_Y,
- RD_PARAM_BLIT_WIDTH,
- RD_PARAM_BLIT_HEIGHT,
- RD_PARAM_BLIT_X2, /* BLIT_X + BLIT_WIDTH */
- RD_PARAM_BLIT_Y2, /* BLIT_Y + BLIT_WIDTH */
+ RD_PARAM_SURFACE_WIDTH,
+ RD_PARAM_SURFACE_HEIGHT,
+ RD_PARAM_SURFACE_PITCH,
+ RD_PARAM_COLOR,
+ RD_PARAM_BLIT_X,
+ RD_PARAM_BLIT_Y,
+ RD_PARAM_BLIT_WIDTH,
+ RD_PARAM_BLIT_HEIGHT,
+ RD_PARAM_BLIT_X2, /* BLIT_X + BLIT_WIDTH */
+ RD_PARAM_BLIT_Y2, /* BLIT_Y + BLIT_WIDTH */
};
void rd_start(const char *name, const char *fmt, ...) __attribute__((weak));
void rd_end(void) __attribute__((weak));
-void rd_write_section(enum rd_sect_type type, const void *buf, int sz) __attribute__((weak));
+void rd_write_section(enum rd_sect_type type, const void *buf, int sz)
+ __attribute__((weak));
/* for code that should run with and without libwrap, use the following
* macros which check if the fxns are present before calling
*/
-#define RD_START(n,f,...) do { if (rd_start) rd_start(n,f,##__VA_ARGS__); } while (0)
-#define RD_END() do { if (rd_end) rd_end(); } while (0)
-#define RD_WRITE_SECTION(t,b,s) do { if (rd_write_section) rd_write_section(t,b,s); } while (0)
+#define RD_START(n, f, ...) \
+ do { \
+ if (rd_start) \
+ rd_start(n, f, ##__VA_ARGS__); \
+ } while (0)
+#define RD_END() \
+ do { \
+ if (rd_end) \
+ rd_end(); \
+ } while (0)
+#define RD_WRITE_SECTION(t, b, s) \
+ do { \
+ if (rd_write_section) \
+ rd_write_section(t, b, s); \
+ } while (0)
#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#undef ALIGN
-#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
+#define ALIGN(v, a) (((v) + (a)-1) & ~((a)-1))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
diff --git a/src/freedreno/decode/rnnutil.c b/src/freedreno/decode/rnnutil.c
index 74e06ac6289..5178f676e7a 100644
--- a/src/freedreno/decode/rnnutil.c
+++ b/src/freedreno/decode/rnnutil.c
@@ -26,183 +26,198 @@
* Rob Clark <robclark@freedesktop.org>
*/
+#include <assert.h>
#include <err.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
-#include <assert.h>
#include "rnnutil.h"
-static struct rnndomain *finddom(struct rnn *rnn, uint32_t regbase)
+static struct rnndomain *
+finddom(struct rnn *rnn, uint32_t regbase)
{
- if (rnndec_checkaddr(rnn->vc, rnn->dom[0], regbase, 0))
- return rnn->dom[0];
- return rnn->dom[1];
+ if (rnndec_checkaddr(rnn->vc, rnn->dom[0], regbase, 0))
+ return rnn->dom[0];
+ return rnn->dom[1];
}
-void _rnn_init(struct rnn *rnn, int nocolor)
+void
+_rnn_init(struct rnn *rnn, int nocolor)
{
- rnn_init();
-
- rnn->db = rnn_newdb();
- rnn->vc_nocolor = rnndec_newcontext(rnn->db);
- rnn->vc_nocolor->colors = &envy_null_colors;
- if (nocolor) {
- rnn->vc = rnn->vc_nocolor;
- } else {
- rnn->vc = rnndec_newcontext(rnn->db);
- rnn->vc->colors = &envy_def_colors;
- }
+ rnn_init();
+
+ rnn->db = rnn_newdb();
+ rnn->vc_nocolor = rnndec_newcontext(rnn->db);
+ rnn->vc_nocolor->colors = &envy_null_colors;
+ if (nocolor) {
+ rnn->vc = rnn->vc_nocolor;
+ } else {
+ rnn->vc = rnndec_newcontext(rnn->db);
+ rnn->vc->colors = &envy_def_colors;
+ }
}
-struct rnn *rnn_new(int nocolor)
+struct rnn *
+rnn_new(int nocolor)
{
- struct rnn *rnn = calloc(sizeof(*rnn), 1);
+ struct rnn *rnn = calloc(sizeof(*rnn), 1);
- if (!rnn)
- return NULL;
+ if (!rnn)
+ return NULL;
- _rnn_init(rnn, nocolor);
+ _rnn_init(rnn, nocolor);
- return rnn;
+ return rnn;
}
-static void init(struct rnn *rnn, char *file, char *domain)
+static void
+init(struct rnn *rnn, char *file, char *domain)
{
- /* prepare rnn stuff for lookup */
- rnn_parsefile(rnn->db, file);
- rnn_prepdb(rnn->db);
- rnn->dom[0] = rnn_finddomain(rnn->db, domain);
- if ((strcmp(domain, "A2XX") == 0) || (strcmp(domain, "A3XX") == 0)) {
- rnn->dom[1] = rnn_finddomain(rnn->db, "AXXX");
- } else {
- rnn->dom[1] = rnn->dom[0];
- }
- if (!rnn->dom[0] && rnn->dom[1]) {
- fprintf(stderr, "Could not find domain %s in %s\n", domain, file);
- }
- rnn->variant = domain;
-
- rnndec_varadd(rnn->vc, "chip", domain);
- if (rnn->vc != rnn->vc_nocolor)
- rnndec_varadd(rnn->vc_nocolor, "chip", domain);
- if (rnn->db->estatus)
- errx(rnn->db->estatus, "failed to parse register database");
+ /* prepare rnn stuff for lookup */
+ rnn_parsefile(rnn->db, file);
+ rnn_prepdb(rnn->db);
+ rnn->dom[0] = rnn_finddomain(rnn->db, domain);
+ if ((strcmp(domain, "A2XX") == 0) || (strcmp(domain, "A3XX") == 0)) {
+ rnn->dom[1] = rnn_finddomain(rnn->db, "AXXX");
+ } else {
+ rnn->dom[1] = rnn->dom[0];
+ }
+ if (!rnn->dom[0] && rnn->dom[1]) {
+ fprintf(stderr, "Could not find domain %s in %s\n", domain, file);
+ }
+ rnn->variant = domain;
+
+ rnndec_varadd(rnn->vc, "chip", domain);
+ if (rnn->vc != rnn->vc_nocolor)
+ rnndec_varadd(rnn->vc_nocolor, "chip", domain);
+ if (rnn->db->estatus)
+ errx(rnn->db->estatus, "failed to parse register database");
}
-void rnn_load_file(struct rnn *rnn, char *file, char *domain)
+void
+rnn_load_file(struct rnn *rnn, char *file, char *domain)
{
- init(rnn, file, domain);
+ init(rnn, file, domain);
}
-void rnn_load(struct rnn *rnn, const char *gpuname)
+void
+rnn_load(struct rnn *rnn, const char *gpuname)
{
- if (strstr(gpuname, "a2")) {
- init(rnn, "adreno/a2xx.xml", "A2XX");
- } else if (strstr(gpuname, "a3")) {
- init(rnn, "adreno/a3xx.xml", "A3XX");
- } else if (strstr(gpuname, "a4")) {
- init(rnn, "adreno/a4xx.xml", "A4XX");
- } else if (strstr(gpuname, "a5")) {
- init(rnn, "adreno/a5xx.xml", "A5XX");
- } else if (strstr(gpuname, "a6")) {
- init(rnn, "adreno/a6xx.xml", "A6XX");
- }
+ if (strstr(gpuname, "a2")) {
+ init(rnn, "adreno/a2xx.xml", "A2XX");
+ } else if (strstr(gpuname, "a3")) {
+ init(rnn, "adreno/a3xx.xml", "A3XX");
+ } else if (strstr(gpuname, "a4")) {
+ init(rnn, "adreno/a4xx.xml", "A4XX");
+ } else if (strstr(gpuname, "a5")) {
+ init(rnn, "adreno/a5xx.xml", "A5XX");
+ } else if (strstr(gpuname, "a6")) {
+ init(rnn, "adreno/a6xx.xml", "A6XX");
+ }
}
-uint32_t rnn_regbase(struct rnn *rnn, const char *name)
+uint32_t
+rnn_regbase(struct rnn *rnn, const char *name)
{
- uint32_t regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[0], name);
- if (!regbase)
- regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[1], name);
- return regbase;
+ uint32_t regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[0], name);
+ if (!regbase)
+ regbase = rnndec_decodereg(rnn->vc_nocolor, rnn->dom[1], name);
+ return regbase;
}
-const char *rnn_regname(struct rnn *rnn, uint32_t regbase, int color)
+const char *
+rnn_regname(struct rnn *rnn, uint32_t regbase, int color)
{
- static char buf[128];
- struct rnndecaddrinfo *info;
-
- info = rnndec_decodeaddr(color ? rnn->vc : rnn->vc_nocolor,
- finddom(rnn, regbase), regbase, 0);
- if (info) {
- strcpy(buf, info->name);
- free(info->name);
- free(info);
- return buf;
- }
- return NULL;
+ static char buf[128];
+ struct rnndecaddrinfo *info;
+
+ info = rnndec_decodeaddr(color ? rnn->vc : rnn->vc_nocolor,
+ finddom(rnn, regbase), regbase, 0);
+ if (info) {
+ strcpy(buf, info->name);
+ free(info->name);
+ free(info);
+ return buf;
+ }
+ return NULL;
}
-struct rnndecaddrinfo *rnn_reginfo(struct rnn *rnn, uint32_t regbase)
+struct rnndecaddrinfo *
+rnn_reginfo(struct rnn *rnn, uint32_t regbase)
{
- return rnndec_decodeaddr(rnn->vc, finddom(rnn, regbase), regbase, 0);
+ return rnndec_decodeaddr(rnn->vc, finddom(rnn, regbase), regbase, 0);
}
-const char *rnn_enumname(struct rnn *rnn, const char *name, uint32_t val)
+const char *
+rnn_enumname(struct rnn *rnn, const char *name, uint32_t val)
{
- return rnndec_decode_enum(rnn->vc, name, val);
+ return rnndec_decode_enum(rnn->vc, name, val);
}
-static struct rnndelem *regelem(struct rnndomain *domain, const char *name)
+static struct rnndelem *
+regelem(struct rnndomain *domain, const char *name)
{
- int i;
- for (i = 0; i < domain->subelemsnum; i++) {
- struct rnndelem *elem = domain->subelems[i];
- if (!strcmp(elem->name, name))
- return elem;
- }
- return NULL;
+ int i;
+ for (i = 0; i < domain->subelemsnum; i++) {
+ struct rnndelem *elem = domain->subelems[i];
+ if (!strcmp(elem->name, name))
+ return elem;
+ }
+ return NULL;
}
/* Lookup rnndelem by name: */
-struct rnndelem *rnn_regelem(struct rnn *rnn, const char *name)
+struct rnndelem *
+rnn_regelem(struct rnn *rnn, const char *name)
{
- struct rnndelem *elem = regelem(rnn->dom[0], name);
- if (elem)
- return elem;
- return regelem(rnn->dom[1], name);
+ struct rnndelem *elem = regelem(rnn->dom[0], name);
+ if (elem)
+ return elem;
+ return regelem(rnn->dom[1], name);
}
-static struct rnndelem *regoff(struct rnndomain *domain, uint32_t offset)
+static struct rnndelem *
+regoff(struct rnndomain *domain, uint32_t offset)
{
- int i;
- for (i = 0; i < domain->subelemsnum; i++) {
- struct rnndelem *elem = domain->subelems[i];
- if (elem->offset == offset)
- return elem;
- }
- return NULL;
+ int i;
+ for (i = 0; i < domain->subelemsnum; i++) {
+ struct rnndelem *elem = domain->subelems[i];
+ if (elem->offset == offset)
+ return elem;
+ }
+ return NULL;
}
/* Lookup rnndelem by offset: */
-struct rnndelem *rnn_regoff(struct rnn *rnn, uint32_t offset)
+struct rnndelem *
+rnn_regoff(struct rnn *rnn, uint32_t offset)
{
- struct rnndelem *elem = regoff(rnn->dom[0], offset);
- if (elem)
- return elem;
- return regoff(rnn->dom[1], offset);
+ struct rnndelem *elem = regoff(rnn->dom[0], offset);
+ if (elem)
+ return elem;
+ return regoff(rnn->dom[1], offset);
}
-enum rnnttype rnn_decodelem(struct rnn *rnn, struct rnntypeinfo *info,
- uint32_t regval, union rnndecval *val)
+enum rnnttype
+rnn_decodelem(struct rnn *rnn, struct rnntypeinfo *info, uint32_t regval,
+ union rnndecval *val)
{
- val->u = regval;
- switch (info->type) {
- case RNN_TTYPE_INLINE_ENUM:
- case RNN_TTYPE_ENUM:
- case RNN_TTYPE_HEX:
- case RNN_TTYPE_INT:
- case RNN_TTYPE_UINT:
- case RNN_TTYPE_FLOAT:
- case RNN_TTYPE_BOOLEAN:
- return info->type;
- case RNN_TTYPE_FIXED:
- case RNN_TTYPE_UFIXED:
- /* TODO */
- default:
- return RNN_TTYPE_INVALID;
- }
+ val->u = regval;
+ switch (info->type) {
+ case RNN_TTYPE_INLINE_ENUM:
+ case RNN_TTYPE_ENUM:
+ case RNN_TTYPE_HEX:
+ case RNN_TTYPE_INT:
+ case RNN_TTYPE_UINT:
+ case RNN_TTYPE_FLOAT:
+ case RNN_TTYPE_BOOLEAN:
+ return info->type;
+ case RNN_TTYPE_FIXED:
+ case RNN_TTYPE_UFIXED:
+ /* TODO */
+ default:
+ return RNN_TTYPE_INVALID;
+ }
}
diff --git a/src/freedreno/decode/rnnutil.h b/src/freedreno/decode/rnnutil.h
index ea667470a89..b6c65b306a4 100644
--- a/src/freedreno/decode/rnnutil.h
+++ b/src/freedreno/decode/rnnutil.h
@@ -29,24 +29,24 @@
#ifndef RNNUTIL_H_
#define RNNUTIL_H_
+#include <assert.h>
#include <stdint.h>
#include <string.h>
-#include <assert.h>
#include "rnn.h"
#include "rnndec.h"
struct rnn {
- struct rnndb *db;
- struct rnndeccontext *vc, *vc_nocolor;
- struct rnndomain *dom[2];
- const char *variant;
+ struct rnndb *db;
+ struct rnndeccontext *vc, *vc_nocolor;
+ struct rnndomain *dom[2];
+ const char *variant;
};
union rnndecval {
- uint32_t u;
- int32_t i;
- float f;
+ uint32_t u;
+ int32_t i;
+ float f;
};
void _rnn_init(struct rnn *rnn, int nocolor);
@@ -61,6 +61,6 @@ const char *rnn_enumname(struct rnn *rnn, const char *name, uint32_t val);
struct rnndelem *rnn_regelem(struct rnn *rnn, const char *name);
struct rnndelem *rnn_regoff(struct rnn *rnn, uint32_t offset);
enum rnnttype rnn_decodelem(struct rnn *rnn, struct rnntypeinfo *info,
- uint32_t regval, union rnndecval *val);
+ uint32_t regval, union rnndecval *val);
#endif /* RNNUTIL_H_ */
diff --git a/src/freedreno/decode/script.c b/src/freedreno/decode/script.c
index a15f5596638..c32c37aad09 100644
--- a/src/freedreno/decode/script.c
+++ b/src/freedreno/decode/script.c
@@ -28,26 +28,29 @@
#define LUA_COMPAT_APIINTCASTS
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <lua.h>
+#include <assert.h>
#include <lauxlib.h>
+#include <lua.h>
#include <lualib.h>
-#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#include "script.h"
#include "cffdec.h"
#include "rnnutil.h"
+#include "script.h"
static lua_State *L;
#if 0
-#define DBG(fmt, ...) \
- do { printf(" ** %s:%d ** "fmt "\n", \
- __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
+#define DBG(fmt, ...) \
+ do { \
+ printf(" ** %s:%d ** " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
#else
-#define DBG(fmt, ...) do {} while (0)
+#define DBG(fmt, ...) \
+ do { \
+ } while (0)
#endif
/* An rnn based decoder, which can either be decoding current register
@@ -55,37 +58,40 @@ static lua_State *L;
*
*/
struct rnndec {
- struct rnn base;
+ struct rnn base;
- /* for pm4 packet decoding: */
- uint32_t sizedwords;
- uint32_t *dwords;
+ /* for pm4 packet decoding: */
+ uint32_t sizedwords;
+ uint32_t *dwords;
};
-static inline struct rnndec *to_rnndec(struct rnn *rnn)
+static inline struct rnndec *
+to_rnndec(struct rnn *rnn)
{
- return (struct rnndec *)rnn;
+ return (struct rnndec *)rnn;
}
-static uint32_t rnn_val(struct rnn *rnn, uint32_t regbase)
+static uint32_t
+rnn_val(struct rnn *rnn, uint32_t regbase)
{
- struct rnndec *rnndec = to_rnndec(rnn);
+ struct rnndec *rnndec = to_rnndec(rnn);
- if (!rnndec->sizedwords) {
- return reg_val(regbase);
- } else if (regbase < rnndec->sizedwords) {
- return rnndec->dwords[regbase];
- } else {
- // XXX throw an error
- return -1;
- }
+ if (!rnndec->sizedwords) {
+ return reg_val(regbase);
+ } else if (regbase < rnndec->sizedwords) {
+ return rnndec->dwords[regbase];
+ } else {
+ // XXX throw an error
+ return -1;
+ }
}
/* does not return */
-static void error(const char *fmt)
+static void
+error(const char *fmt)
{
- fprintf(stderr, fmt, lua_tostring(L, -1));
- exit(1);
+ fprintf(stderr, fmt, lua_tostring(L, -1));
+ exit(1);
}
/*
@@ -93,136 +99,141 @@ static void error(const char *fmt)
*/
struct rnndenum {
- const char *str;
- int val;
+ const char *str;
+ int val;
};
-static int l_meta_rnn_enum_tostring(lua_State *L)
+static int
+l_meta_rnn_enum_tostring(lua_State *L)
{
- struct rnndenum *e = lua_touserdata(L, 1);
- if (e->str) {
- lua_pushstring(L, e->str);
- } else {
- char buf[32];
- sprintf(buf, "%u", e->val);
- lua_pushstring(L, buf);
- }
- return 1;
+ struct rnndenum *e = lua_touserdata(L, 1);
+ if (e->str) {
+ lua_pushstring(L, e->str);
+ } else {
+ char buf[32];
+ sprintf(buf, "%u", e->val);
+ lua_pushstring(L, buf);
+ }
+ return 1;
}
/* so, this doesn't actually seem to be implemented yet, but hopefully
* some day lua comes to it's senses
*/
-static int l_meta_rnn_enum_tonumber(lua_State *L)
+static int
+l_meta_rnn_enum_tonumber(lua_State *L)
{
- struct rnndenum *e = lua_touserdata(L, 1);
- lua_pushinteger(L, e->val);
- return 1;
+ struct rnndenum *e = lua_touserdata(L, 1);
+ lua_pushinteger(L, e->val);
+ return 1;
}
static const struct luaL_Reg l_meta_rnn_enum[] = {
- {"__tostring", l_meta_rnn_enum_tostring},
- {"__tonumber", l_meta_rnn_enum_tonumber},
- {NULL, NULL} /* sentinel */
+ {"__tostring", l_meta_rnn_enum_tostring},
+ {"__tonumber", l_meta_rnn_enum_tonumber},
+ {NULL, NULL} /* sentinel */
};
-static void pushenum(struct lua_State *L, int val, struct rnnenum *info)
+static void
+pushenum(struct lua_State *L, int val, struct rnnenum *info)
{
- struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
+ struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
- e->val = val;
- e->str = NULL;
+ e->val = val;
+ e->str = NULL;
- for (int i = 0; i < info->valsnum; i++) {
- if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
- e->str = info->vals[i]->name;
- break;
- }
- }
+ for (int i = 0; i < info->valsnum; i++) {
+ if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
+ e->str = info->vals[i]->name;
+ break;
+ }
+ }
- luaL_newmetatable(L, "rnnmetaenum");
- luaL_setfuncs(L, l_meta_rnn_enum, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmetaenum");
+ luaL_setfuncs(L, l_meta_rnn_enum, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmetaenum");
+ luaL_setmetatable(L, "rnnmetaenum");
}
/* Expose rnn decode to script environment as "rnn" library:
*/
struct rnndoff {
- struct rnn *rnn;
- struct rnndelem *elem;
- uint64_t offset;
+ struct rnn *rnn;
+ struct rnndelem *elem;
+ uint64_t offset;
};
-static void push_rnndoff(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset)
+static void
+push_rnndoff(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset)
{
- struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
- rnndoff->rnn = rnn;
- rnndoff->elem = elem;
- rnndoff->offset = offset;
+ struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
+ rnndoff->rnn = rnn;
+ rnndoff->elem = elem;
+ rnndoff->offset = offset;
}
static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset);
-static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset);
-
-static int pushdecval(struct lua_State *L, struct rnn *rnn,
- uint32_t regval, struct rnntypeinfo *info)
-{
- union rnndecval val;
- switch (rnn_decodelem(rnn, info, regval, &val)) {
- case RNN_TTYPE_ENUM:
- case RNN_TTYPE_INLINE_ENUM:
- pushenum(L, val.i, info->eenum);
- return 1;
- case RNN_TTYPE_INT:
- lua_pushinteger(L, val.i);
- return 1;
- case RNN_TTYPE_UINT:
- case RNN_TTYPE_HEX:
- lua_pushunsigned(L, val.u);
- return 1;
- case RNN_TTYPE_FLOAT:
- lua_pushnumber(L, val.f);
- return 1;
- case RNN_TTYPE_BOOLEAN:
- lua_pushboolean(L, val.u);
- return 1;
- case RNN_TTYPE_INVALID:
- default:
- return 0;
- }
-
-}
-
-static int l_rnn_etype(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset)
-{
- int ret;
- uint32_t regval;
- DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
- switch (elem->type) {
- case RNN_ETYPE_REG:
- /* if a register has no bitfields, just return
- * the raw value:
- */
- regval = rnn_val(rnn, offset);
- regval <<= elem->typeinfo.shr;
- ret = pushdecval(L, rnn, regval, &elem->typeinfo);
- if (ret)
- return ret;
- return l_rnn_etype_reg(L, rnn, elem, offset);
- case RNN_ETYPE_ARRAY:
- return l_rnn_etype_array(L, rnn, elem, offset);
- default:
- /* hmm.. */
- printf("unhandled type: %d\n", elem->type);
- return 0;
- }
+ struct rnndelem *elem, uint64_t offset);
+static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset);
+
+static int
+pushdecval(struct lua_State *L, struct rnn *rnn, uint32_t regval,
+ struct rnntypeinfo *info)
+{
+ union rnndecval val;
+ switch (rnn_decodelem(rnn, info, regval, &val)) {
+ case RNN_TTYPE_ENUM:
+ case RNN_TTYPE_INLINE_ENUM:
+ pushenum(L, val.i, info->eenum);
+ return 1;
+ case RNN_TTYPE_INT:
+ lua_pushinteger(L, val.i);
+ return 1;
+ case RNN_TTYPE_UINT:
+ case RNN_TTYPE_HEX:
+ lua_pushunsigned(L, val.u);
+ return 1;
+ case RNN_TTYPE_FLOAT:
+ lua_pushnumber(L, val.f);
+ return 1;
+ case RNN_TTYPE_BOOLEAN:
+ lua_pushboolean(L, val.u);
+ return 1;
+ case RNN_TTYPE_INVALID:
+ default:
+ return 0;
+ }
+}
+
+static int
+l_rnn_etype(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset)
+{
+ int ret;
+ uint32_t regval;
+ DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
+ switch (elem->type) {
+ case RNN_ETYPE_REG:
+ /* if a register has no bitfields, just return
+ * the raw value:
+ */
+ regval = rnn_val(rnn, offset);
+ regval <<= elem->typeinfo.shr;
+ ret = pushdecval(L, rnn, regval, &elem->typeinfo);
+ if (ret)
+ return ret;
+ return l_rnn_etype_reg(L, rnn, elem, offset);
+ case RNN_ETYPE_ARRAY:
+ return l_rnn_etype_array(L, rnn, elem, offset);
+ default:
+ /* hmm.. */
+ printf("unhandled type: %d\n", elem->type);
+ return 0;
+ }
}
/*
@@ -231,316 +242,327 @@ static int l_rnn_etype(lua_State *L, struct rnn *rnn,
* to represent the current array index (ie. 'RB_MRT[n]')
*/
-static int l_rnn_struct_meta_index(lua_State *L)
+static int
+l_rnn_struct_meta_index(lua_State *L)
{
- struct rnndoff *rnndoff = lua_touserdata(L, 1);
- const char *name = lua_tostring(L, 2);
- struct rnndelem *elem = rnndoff->elem;
- int i;
+ struct rnndoff *rnndoff = lua_touserdata(L, 1);
+ const char *name = lua_tostring(L, 2);
+ struct rnndelem *elem = rnndoff->elem;
+ int i;
- for (i = 0; i < elem->subelemsnum; i++) {
- struct rnndelem *subelem = elem->subelems[i];
- if (!strcmp(name, subelem->name)) {
- return l_rnn_etype(L, rnndoff->rnn, subelem,
- rnndoff->offset + subelem->offset);
- }
- }
+ for (i = 0; i < elem->subelemsnum; i++) {
+ struct rnndelem *subelem = elem->subelems[i];
+ if (!strcmp(name, subelem->name)) {
+ return l_rnn_etype(L, rnndoff->rnn, subelem,
+ rnndoff->offset + subelem->offset);
+ }
+ }
- return 0;
+ return 0;
}
static const struct luaL_Reg l_meta_rnn_struct[] = {
- {"__index", l_rnn_struct_meta_index},
- {NULL, NULL} /* sentinel */
+ {"__index", l_rnn_struct_meta_index}, {NULL, NULL} /* sentinel */
};
-static int l_rnn_etype_struct(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset)
+static int
+l_rnn_etype_struct(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset)
{
- push_rnndoff(L, rnn, elem, offset);
+ push_rnndoff(L, rnn, elem, offset);
- luaL_newmetatable(L, "rnnmetastruct");
- luaL_setfuncs(L, l_meta_rnn_struct, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmetastruct");
+ luaL_setfuncs(L, l_meta_rnn_struct, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmetastruct");
+ luaL_setmetatable(L, "rnnmetastruct");
- return 1;
+ return 1;
}
/*
* Array Object:
*/
-static int l_rnn_array_meta_index(lua_State *L)
+static int
+l_rnn_array_meta_index(lua_State *L)
{
- struct rnndoff *rnndoff = lua_touserdata(L, 1);
- int idx = lua_tointeger(L, 2);
- struct rnndelem *elem = rnndoff->elem;
- uint64_t offset = rnndoff->offset + (elem->stride * idx);
+ struct rnndoff *rnndoff = lua_touserdata(L, 1);
+ int idx = lua_tointeger(L, 2);
+ struct rnndelem *elem = rnndoff->elem;
+ uint64_t offset = rnndoff->offset + (elem->stride * idx);
- DBG("rnndoff=%p, idx=%d, numsubelems=%d",
- rnndoff, idx, rnndoff->elem->subelemsnum);
+ DBG("rnndoff=%p, idx=%d, numsubelems=%d", rnndoff, idx,
+ rnndoff->elem->subelemsnum);
- /* if just a single sub-element, it is directly a register,
- * otherwise we need to accumulate the array index while
- * we wait for the register name within the array..
- */
- if (elem->subelemsnum == 1) {
- return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
- } else {
- return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
- }
+ /* if just a single sub-element, it is directly a register,
+ * otherwise we need to accumulate the array index while
+ * we wait for the register name within the array..
+ */
+ if (elem->subelemsnum == 1) {
+ return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
+ } else {
+ return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
+ }
- return 0;
+ return 0;
}
static const struct luaL_Reg l_meta_rnn_array[] = {
- {"__index", l_rnn_array_meta_index},
- {NULL, NULL} /* sentinel */
+ {"__index", l_rnn_array_meta_index}, {NULL, NULL} /* sentinel */
};
-static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset)
+static int
+l_rnn_etype_array(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset)
{
- push_rnndoff(L, rnn, elem, offset);
+ push_rnndoff(L, rnn, elem, offset);
- luaL_newmetatable(L, "rnnmetaarray");
- luaL_setfuncs(L, l_meta_rnn_array, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmetaarray");
+ luaL_setfuncs(L, l_meta_rnn_array, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmetaarray");
+ luaL_setmetatable(L, "rnnmetaarray");
- return 1;
+ return 1;
}
/*
* Register element:
*/
-static int l_rnn_reg_meta_index(lua_State *L)
-{
- struct rnndoff *rnndoff = lua_touserdata(L, 1);
- const char *name = lua_tostring(L, 2);
- struct rnndelem *elem = rnndoff->elem;
- struct rnntypeinfo *info = &elem->typeinfo;
- struct rnnbitfield **bitfields;
- int bitfieldsnum;
- int i;
-
- switch (info->type) {
- case RNN_TTYPE_BITSET:
- bitfields = info->ebitset->bitfields;
- bitfieldsnum = info->ebitset->bitfieldsnum;
- break;
- case RNN_TTYPE_INLINE_BITSET:
- bitfields = info->bitfields;
- bitfieldsnum = info->bitfieldsnum;
- break;
- default:
- printf("invalid register type: %d\n", info->type);
- return 0;
- }
-
- for (i = 0; i < bitfieldsnum; i++) {
- struct rnnbitfield *bf = bitfields[i];
- if (!strcmp(name, bf->name)) {
- uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
-
- regval &= typeinfo_mask(&bf->typeinfo);
- regval >>= bf->typeinfo.low;
- regval <<= bf->typeinfo.shr;
-
- DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x",
- name, info, rnndoff->elem->subelemsnum,
- bf->typeinfo.type, regval);
-
- return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
- }
- }
-
- printf("invalid member: %s\n", name);
- return 0;
-}
-
-static int l_rnn_reg_meta_tostring(lua_State *L)
-{
- struct rnndoff *rnndoff = lua_touserdata(L, 1);
- uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
- struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
- char *decoded;
- if (info && info->typeinfo) {
- decoded = rnndec_decodeval(rnndoff->rnn->vc,
- info->typeinfo, regval);
- } else {
- asprintf(&decoded, "%08x", regval);
- }
- lua_pushstring(L, decoded);
- free(decoded);
- if (info) {
- free(info->name);
- free(info);
- }
- return 1;
-}
-
-static int l_rnn_reg_meta_tonumber(lua_State *L)
-{
- struct rnndoff *rnndoff = lua_touserdata(L, 1);
- uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
-
- regval <<= rnndoff->elem->typeinfo.shr;
-
- lua_pushnumber(L, regval);
- return 1;
+static int
+l_rnn_reg_meta_index(lua_State *L)
+{
+ struct rnndoff *rnndoff = lua_touserdata(L, 1);
+ const char *name = lua_tostring(L, 2);
+ struct rnndelem *elem = rnndoff->elem;
+ struct rnntypeinfo *info = &elem->typeinfo;
+ struct rnnbitfield **bitfields;
+ int bitfieldsnum;
+ int i;
+
+ switch (info->type) {
+ case RNN_TTYPE_BITSET:
+ bitfields = info->ebitset->bitfields;
+ bitfieldsnum = info->ebitset->bitfieldsnum;
+ break;
+ case RNN_TTYPE_INLINE_BITSET:
+ bitfields = info->bitfields;
+ bitfieldsnum = info->bitfieldsnum;
+ break;
+ default:
+ printf("invalid register type: %d\n", info->type);
+ return 0;
+ }
+
+ for (i = 0; i < bitfieldsnum; i++) {
+ struct rnnbitfield *bf = bitfields[i];
+ if (!strcmp(name, bf->name)) {
+ uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
+
+ regval &= typeinfo_mask(&bf->typeinfo);
+ regval >>= bf->typeinfo.low;
+ regval <<= bf->typeinfo.shr;
+
+ DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x", name, info,
+ rnndoff->elem->subelemsnum, bf->typeinfo.type, regval);
+
+ return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
+ }
+ }
+
+ printf("invalid member: %s\n", name);
+ return 0;
+}
+
+static int
+l_rnn_reg_meta_tostring(lua_State *L)
+{
+ struct rnndoff *rnndoff = lua_touserdata(L, 1);
+ uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
+ struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
+ char *decoded;
+ if (info && info->typeinfo) {
+ decoded = rnndec_decodeval(rnndoff->rnn->vc, info->typeinfo, regval);
+ } else {
+ asprintf(&decoded, "%08x", regval);
+ }
+ lua_pushstring(L, decoded);
+ free(decoded);
+ if (info) {
+ free(info->name);
+ free(info);
+ }
+ return 1;
+}
+
+static int
+l_rnn_reg_meta_tonumber(lua_State *L)
+{
+ struct rnndoff *rnndoff = lua_touserdata(L, 1);
+ uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
+
+ regval <<= rnndoff->elem->typeinfo.shr;
+
+ lua_pushnumber(L, regval);
+ return 1;
}
static const struct luaL_Reg l_meta_rnn_reg[] = {
- {"__index", l_rnn_reg_meta_index},
- {"__tostring", l_rnn_reg_meta_tostring},
- {"__tonumber", l_rnn_reg_meta_tonumber},
- {NULL, NULL} /* sentinel */
+ {"__index", l_rnn_reg_meta_index},
+ {"__tostring", l_rnn_reg_meta_tostring},
+ {"__tonumber", l_rnn_reg_meta_tonumber},
+ {NULL, NULL} /* sentinel */
};
-static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn,
- struct rnndelem *elem, uint64_t offset)
+static int
+l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
+ uint64_t offset)
{
- push_rnndoff(L, rnn, elem, offset);
+ push_rnndoff(L, rnn, elem, offset);
- luaL_newmetatable(L, "rnnmetareg");
- luaL_setfuncs(L, l_meta_rnn_reg, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmetareg");
+ luaL_setfuncs(L, l_meta_rnn_reg, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmetareg");
+ luaL_setmetatable(L, "rnnmetareg");
- return 1;
+ return 1;
}
/*
*
*/
-static int l_rnn_meta_index(lua_State *L)
+static int
+l_rnn_meta_index(lua_State *L)
{
- struct rnn *rnn = lua_touserdata(L, 1);
- const char *name = lua_tostring(L, 2);
- struct rnndelem *elem;
+ struct rnn *rnn = lua_touserdata(L, 1);
+ const char *name = lua_tostring(L, 2);
+ struct rnndelem *elem;
- elem = rnn_regelem(rnn, name);
- if (!elem)
- return 0;
+ elem = rnn_regelem(rnn, name);
+ if (!elem)
+ return 0;
- return l_rnn_etype(L, rnn, elem, elem->offset);
+ return l_rnn_etype(L, rnn, elem, elem->offset);
}
-static int l_rnn_meta_gc(lua_State *L)
+static int
+l_rnn_meta_gc(lua_State *L)
{
- // TODO
- //struct rnn *rnn = lua_touserdata(L, 1);
- //rnn_deinit(rnn);
- return 0;
+ // TODO
+ // struct rnn *rnn = lua_touserdata(L, 1);
+ // rnn_deinit(rnn);
+ return 0;
}
static const struct luaL_Reg l_meta_rnn[] = {
- {"__index", l_rnn_meta_index},
- {"__gc", l_rnn_meta_gc},
- {NULL, NULL} /* sentinel */
+ {"__index", l_rnn_meta_index},
+ {"__gc", l_rnn_meta_gc},
+ {NULL, NULL} /* sentinel */
};
-static int l_rnn_init(lua_State *L)
+static int
+l_rnn_init(lua_State *L)
{
- const char *gpuname = lua_tostring(L, 1);
- struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
- _rnn_init(&rnndec->base, 0);
- rnn_load(&rnndec->base, gpuname);
- rnndec->sizedwords = 0;
+ const char *gpuname = lua_tostring(L, 1);
+ struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
+ _rnn_init(&rnndec->base, 0);
+ rnn_load(&rnndec->base, gpuname);
+ rnndec->sizedwords = 0;
- luaL_newmetatable(L, "rnnmeta");
- luaL_setfuncs(L, l_meta_rnn, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmeta");
+ luaL_setfuncs(L, l_meta_rnn, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmeta");
+ luaL_setmetatable(L, "rnnmeta");
- return 1;
+ return 1;
}
-static int l_rnn_enumname(lua_State *L)
+static int
+l_rnn_enumname(lua_State *L)
{
- struct rnn *rnn = lua_touserdata(L, 1);
- const char *name = lua_tostring(L, 2);
- uint32_t val = (uint32_t)lua_tonumber(L, 3);
- lua_pushstring(L, rnn_enumname(rnn, name, val));
- return 1;
+ struct rnn *rnn = lua_touserdata(L, 1);
+ const char *name = lua_tostring(L, 2);
+ uint32_t val = (uint32_t)lua_tonumber(L, 3);
+ lua_pushstring(L, rnn_enumname(rnn, name, val));
+ return 1;
}
-static int l_rnn_regname(lua_State *L)
+static int
+l_rnn_regname(lua_State *L)
{
- struct rnn *rnn = lua_touserdata(L, 1);
- uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
- lua_pushstring(L, rnn_regname(rnn, regbase, 1));
- return 1;
+ struct rnn *rnn = lua_touserdata(L, 1);
+ uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
+ lua_pushstring(L, rnn_regname(rnn, regbase, 1));
+ return 1;
}
-static int l_rnn_regval(lua_State *L)
+static int
+l_rnn_regval(lua_State *L)
{
- struct rnn *rnn = lua_touserdata(L, 1);
- uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
- uint32_t regval = (uint32_t)lua_tonumber(L, 3);
- struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
- char *decoded;
- if (info && info->typeinfo) {
- decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
- } else {
- asprintf(&decoded, "%08x", regval);
- }
- lua_pushstring(L, decoded);
- free(decoded);
- if (info) {
- free(info->name);
- free(info);
- }
- return 1;
+ struct rnn *rnn = lua_touserdata(L, 1);
+ uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
+ uint32_t regval = (uint32_t)lua_tonumber(L, 3);
+ struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
+ char *decoded;
+ if (info && info->typeinfo) {
+ decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
+ } else {
+ asprintf(&decoded, "%08x", regval);
+ }
+ lua_pushstring(L, decoded);
+ free(decoded);
+ if (info) {
+ free(info->name);
+ free(info);
+ }
+ return 1;
}
static const struct luaL_Reg l_rnn[] = {
- {"init", l_rnn_init},
- {"enumname", l_rnn_enumname},
- {"regname", l_rnn_regname},
- {"regval", l_rnn_regval},
- {NULL, NULL} /* sentinel */
+ {"init", l_rnn_init},
+ {"enumname", l_rnn_enumname},
+ {"regname", l_rnn_regname},
+ {"regval", l_rnn_regval},
+ {NULL, NULL} /* sentinel */
};
-
-
/* Expose the register state to script enviroment as a "regs" library:
*/
-static int l_reg_written(lua_State *L)
+static int
+l_reg_written(lua_State *L)
{
- uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
- lua_pushnumber(L, reg_written(regbase));
- return 1;
+ uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
+ lua_pushnumber(L, reg_written(regbase));
+ return 1;
}
-static int l_reg_lastval(lua_State *L)
+static int
+l_reg_lastval(lua_State *L)
{
- uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
- lua_pushnumber(L, reg_lastval(regbase));
- return 1;
+ uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
+ lua_pushnumber(L, reg_lastval(regbase));
+ return 1;
}
-static int l_reg_val(lua_State *L)
+static int
+l_reg_val(lua_State *L)
{
- uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
- lua_pushnumber(L, reg_val(regbase));
- return 1;
+ uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
+ lua_pushnumber(L, reg_val(regbase));
+ return 1;
}
static const struct luaL_Reg l_regs[] = {
- {"written", l_reg_written},
- {"lastval", l_reg_lastval},
- {"val", l_reg_val},
- {NULL, NULL} /* sentinel */
+ {"written", l_reg_written},
+ {"lastval", l_reg_lastval},
+ {"val", l_reg_val},
+ {NULL, NULL} /* sentinel */
};
/* Expose API to lookup snapshot buffers:
@@ -550,122 +572,125 @@ uint64_t gpubaseaddr(uint64_t gpuaddr);
unsigned hostlen(uint64_t gpuaddr);
/* given address, return base-address of buffer: */
-static int l_bo_base(lua_State *L)
+static int
+l_bo_base(lua_State *L)
{
- uint64_t addr = (uint64_t)lua_tonumber(L, 1);
- lua_pushnumber(L, gpubaseaddr(addr));
- return 1;
+ uint64_t addr = (uint64_t)lua_tonumber(L, 1);
+ lua_pushnumber(L, gpubaseaddr(addr));
+ return 1;
}
/* given address, return the remaining size of the buffer: */
-static int l_bo_size(lua_State *L)
+static int
+l_bo_size(lua_State *L)
{
- uint64_t addr = (uint64_t)lua_tonumber(L, 1);
- lua_pushnumber(L, hostlen(addr));
- return 1;
+ uint64_t addr = (uint64_t)lua_tonumber(L, 1);
+ lua_pushnumber(L, hostlen(addr));
+ return 1;
}
static const struct luaL_Reg l_bos[] = {
- {"base", l_bo_base},
- {"size", l_bo_size},
- {NULL, NULL} /* sentinel */
+ {"base", l_bo_base}, {"size", l_bo_size}, {NULL, NULL} /* sentinel */
};
-static void openlib(const char *lib, const luaL_Reg *reg)
+static void
+openlib(const char *lib, const luaL_Reg *reg)
{
- lua_newtable(L);
- luaL_setfuncs(L, reg, 0);
- lua_setglobal(L, lib);
+ lua_newtable(L);
+ luaL_setfuncs(L, reg, 0);
+ lua_setglobal(L, lib);
}
/* called at start to load the script: */
-int script_load(const char *file)
+int
+script_load(const char *file)
{
- int ret;
+ int ret;
- assert(!L);
+ assert(!L);
- L = luaL_newstate();
- luaL_openlibs(L);
- openlib("bos", l_bos);
- openlib("regs", l_regs);
- openlib("rnn", l_rnn);
+ L = luaL_newstate();
+ luaL_openlibs(L);
+ openlib("bos", l_bos);
+ openlib("regs", l_regs);
+ openlib("rnn", l_rnn);
- ret = luaL_loadfile(L, file);
- if (ret)
- error("%s\n");
+ ret = luaL_loadfile(L, file);
+ if (ret)
+ error("%s\n");
- ret = lua_pcall(L, 0, LUA_MULTRET, 0);
- if (ret)
- error("%s\n");
+ ret = lua_pcall(L, 0, LUA_MULTRET, 0);
+ if (ret)
+ error("%s\n");
- return 0;
+ return 0;
}
-
/* called at start of each cmdstream file: */
-void script_start_cmdstream(const char *name)
+void
+script_start_cmdstream(const char *name)
{
- if (!L)
- return;
+ if (!L)
+ return;
- lua_getglobal(L, "start_cmdstream");
+ lua_getglobal(L, "start_cmdstream");
- /* if no handler just ignore it: */
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 1);
- return;
- }
+ /* if no handler just ignore it: */
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 1);
+ return;
+ }
- lua_pushstring(L, name);
+ lua_pushstring(L, name);
- /* do the call (1 arguments, 0 result) */
- if (lua_pcall(L, 1, 0, 0) != 0)
- error("error running function `f': %s\n");
+ /* do the call (1 arguments, 0 result) */
+ if (lua_pcall(L, 1, 0, 0) != 0)
+ error("error running function `f': %s\n");
}
/* called at each DRAW_INDX, calls script drawidx fxn to process
* the current state
*/
-void script_draw(const char *primtype, uint32_t nindx)
+void
+script_draw(const char *primtype, uint32_t nindx)
{
- if (!L)
- return;
+ if (!L)
+ return;
- lua_getglobal(L, "draw");
+ lua_getglobal(L, "draw");
- /* if no handler just ignore it: */
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 1);
- return;
- }
+ /* if no handler just ignore it: */
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 1);
+ return;
+ }
- lua_pushstring(L, primtype);
- lua_pushnumber(L, nindx);
+ lua_pushstring(L, primtype);
+ lua_pushnumber(L, nindx);
- /* do the call (2 arguments, 0 result) */
- if (lua_pcall(L, 2, 0, 0) != 0)
- error("error running function `f': %s\n");
+ /* do the call (2 arguments, 0 result) */
+ if (lua_pcall(L, 2, 0, 0) != 0)
+ error("error running function `f': %s\n");
}
-
-static int l_rnn_meta_dom_index(lua_State *L)
+static int
+l_rnn_meta_dom_index(lua_State *L)
{
- struct rnn *rnn = lua_touserdata(L, 1);
- uint32_t offset = (uint32_t)lua_tonumber(L, 2);
- struct rnndelem *elem;
+ struct rnn *rnn = lua_touserdata(L, 1);
+ uint32_t offset = (uint32_t)lua_tonumber(L, 2);
+ struct rnndelem *elem;
- /* TODO might be nicer if the arg isn't a number, to search the domain
- * for matching bitfields.. so that the script could do something like
- * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
- * offset of the dword containing the bitfield..
- */
+ /* TODO might be nicer if the arg isn't a number, to search the domain
+ * for matching bitfields.. so that the script could do something like
+ * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
+ * offset of the dword containing the bitfield..
+ */
- elem = rnn_regoff(rnn, offset);
- if (!elem)
- return 0;
+ elem = rnn_regoff(rnn, offset);
+ if (!elem)
+ return 0;
- return l_rnn_etype(L, rnn, elem, elem->offset);
+ return l_rnn_etype(L, rnn, elem, elem->offset);
}
/*
@@ -674,101 +699,108 @@ static int l_rnn_meta_dom_index(lua_State *L)
* decoding for the individual dwords and bitfields.
*/
-static int l_rnn_meta_dom_gc(lua_State *L)
+static int
+l_rnn_meta_dom_gc(lua_State *L)
{
- // TODO
- //struct rnn *rnn = lua_touserdata(L, 1);
- //rnn_deinit(rnn);
- return 0;
+ // TODO
+ // struct rnn *rnn = lua_touserdata(L, 1);
+ // rnn_deinit(rnn);
+ return 0;
}
static const struct luaL_Reg l_meta_rnn_dom[] = {
- {"__index", l_rnn_meta_dom_index},
- {"__gc", l_rnn_meta_dom_gc},
- {NULL, NULL} /* sentinel */
+ {"__index", l_rnn_meta_dom_index},
+ {"__gc", l_rnn_meta_dom_gc},
+ {NULL, NULL} /* sentinel */
};
/* called to general pm4 packet decoding, such as texture/sampler state
*/
-void script_packet(uint32_t *dwords, uint32_t sizedwords,
- struct rnn *rnn, struct rnndomain *dom)
+void
+script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
+ struct rnndomain *dom)
{
- if (!L)
- return;
+ if (!L)
+ return;
- lua_getglobal(L, dom->name);
+ lua_getglobal(L, dom->name);
- /* if no handler for the packet, just ignore it: */
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 1);
- return;
- }
+ /* if no handler for the packet, just ignore it: */
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 1);
+ return;
+ }
- struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
+ struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
- rnndec->base = *rnn;
- rnndec->base.dom[0] = dom;
- rnndec->base.dom[1] = NULL;
- rnndec->dwords = dwords;
- rnndec->sizedwords = sizedwords;
+ rnndec->base = *rnn;
+ rnndec->base.dom[0] = dom;
+ rnndec->base.dom[1] = NULL;
+ rnndec->dwords = dwords;
+ rnndec->sizedwords = sizedwords;
- luaL_newmetatable(L, "rnnmetadom");
- luaL_setfuncs(L, l_meta_rnn_dom, 0);
- lua_pop(L, 1);
+ luaL_newmetatable(L, "rnnmetadom");
+ luaL_setfuncs(L, l_meta_rnn_dom, 0);
+ lua_pop(L, 1);
- luaL_setmetatable(L, "rnnmetadom");
+ luaL_setmetatable(L, "rnnmetadom");
- lua_pushnumber(L, sizedwords);
+ lua_pushnumber(L, sizedwords);
- if (lua_pcall(L, 2, 0, 0) != 0)
- error("error running function `f': %s\n");
+ if (lua_pcall(L, 2, 0, 0) != 0)
+ error("error running function `f': %s\n");
}
/* helper to call fxn that takes and returns void: */
-static void simple_call(const char *name)
+static void
+simple_call(const char *name)
{
- if (!L)
- return;
+ if (!L)
+ return;
- lua_getglobal(L, name);
+ lua_getglobal(L, name);
- /* if no handler just ignore it: */
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 1);
- return;
- }
+ /* if no handler just ignore it: */
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 1);
+ return;
+ }
- /* do the call (0 arguments, 0 result) */
- if (lua_pcall(L, 0, 0, 0) != 0)
- error("error running function `f': %s\n");
+ /* do the call (0 arguments, 0 result) */
+ if (lua_pcall(L, 0, 0, 0) != 0)
+ error("error running function `f': %s\n");
}
/* called at end of each cmdstream file: */
-void script_end_cmdstream(void)
+void
+script_end_cmdstream(void)
{
- simple_call("end_cmdstream");
+ simple_call("end_cmdstream");
}
/* called at start of submit/issueibcmds: */
-void script_start_submit(void)
+void
+script_start_submit(void)
{
- simple_call("start_submit");
+ simple_call("start_submit");
}
/* called at end of submit/issueibcmds: */
-void script_end_submit(void)
+void
+script_end_submit(void)
{
- simple_call("end_submit");
+ simple_call("end_submit");
}
/* called after last cmdstream file: */
-void script_finish(void)
+void
+script_finish(void)
{
- if (!L)
- return;
+ if (!L)
+ return;
- simple_call("finish");
+ simple_call("finish");
- lua_close(L);
- L = NULL;
+ lua_close(L);
+ L = NULL;
}
diff --git a/src/freedreno/decode/script.h b/src/freedreno/decode/script.h
index d14b69ae8f7..de57ed7ece1 100644
--- a/src/freedreno/decode/script.h
+++ b/src/freedreno/decode/script.h
@@ -31,7 +31,6 @@
#include <stdint.h>
-
// XXX make script support optional
#define ENABLE_SCRIPTING 1
@@ -53,7 +52,8 @@ struct rnn;
struct rnndomain;
__attribute__((weak))
void script_packet(uint32_t *dwords, uint32_t sizedwords,
- struct rnn *rnn, struct rnndomain *dom);
+ struct rnn *rnn,
+ struct rnndomain *dom);
/* maybe at some point it is interesting to add additional script
* hooks for CP_EVENT_WRITE, etc?
@@ -72,5 +72,4 @@ void script_finish(void);
// TODO no-op stubs..
#endif
-
#endif /* SCRIPT_H_ */
diff --git a/src/freedreno/decode/util.h b/src/freedreno/decode/util.h
index 1ec02023b49..497f5615000 100644
--- a/src/freedreno/decode/util.h
+++ b/src/freedreno/decode/util.h
@@ -30,175 +30,177 @@
/* old-style program binary XOR'd ascii w/ 0xff */
#ifndef ASCII_XOR
-# define ASCII_XOR 0
+#define ASCII_XOR 0
#endif
-static inline const char *tab(int lvl)
+static inline const char *
+tab(int lvl)
{
- const char *TAB = "\t\t\t\t\t\t\t\t\0";
- return &TAB[strlen(TAB) - lvl];
+ const char *TAB = "\t\t\t\t\t\t\t\t\0";
+ return &TAB[strlen(TAB) - lvl];
}
/* convert float to dword */
-static inline float d2f(uint32_t d)
+static inline float
+d2f(uint32_t d)
{
- union {
- float f;
- uint32_t d;
- } u = {
- .d = d,
- };
- return u.f;
+ union {
+ float f;
+ uint32_t d;
+ } u = {
+ .d = d,
+ };
+ return u.f;
}
-static inline void dump_hex(const void *buf, int sz)
+static inline void
+dump_hex(const void *buf, int sz)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz;
- int i = 0;
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz;
+ int i = 0;
- while (ptr < end) {
- uint32_t d = 0;
+ while (ptr < end) {
+ uint32_t d = 0;
- printf((i % 8) ? " " : "\t");
+ printf((i % 8) ? " " : "\t");
- d |= *(ptr++) << 0;
- d |= *(ptr++) << 8;
- d |= *(ptr++) << 16;
- d |= *(ptr++) << 24;
+ d |= *(ptr++) << 0;
+ d |= *(ptr++) << 8;
+ d |= *(ptr++) << 16;
+ d |= *(ptr++) << 24;
- printf("%08x", d);
+ printf("%08x", d);
- if ((i % 8) == 7) {
- printf("\n");
- }
+ if ((i % 8) == 7) {
+ printf("\n");
+ }
- i++;
- }
+ i++;
+ }
- if (i % 8) {
- printf("\n");
- }
+ if (i % 8) {
+ printf("\n");
+ }
}
static inline void
dump_float(const void *buf, int sz)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz - 3;
- int i = 0;
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz - 3;
+ int i = 0;
- while (ptr < end) {
- uint32_t d = 0;
+ while (ptr < end) {
+ uint32_t d = 0;
- printf((i % 8) ? " " : "\t");
+ printf((i % 8) ? " " : "\t");
- d |= *(ptr++) << 0;
- d |= *(ptr++) << 8;
- d |= *(ptr++) << 16;
- d |= *(ptr++) << 24;
+ d |= *(ptr++) << 0;
+ d |= *(ptr++) << 8;
+ d |= *(ptr++) << 16;
+ d |= *(ptr++) << 24;
- printf("%8f", d2f(d));
+ printf("%8f", d2f(d));
- if ((i % 8) == 7) {
- printf("\n");
- }
+ if ((i % 8) == 7) {
+ printf("\n");
+ }
- i++;
- }
+ i++;
+ }
- if (i % 8) {
- printf("\n");
- }
+ if (i % 8) {
+ printf("\n");
+ }
}
-#define is_ok_ascii(c) \
- (isascii(c) && ((c == '\t') || !iscntrl(c)))
+#define is_ok_ascii(c) (isascii(c) && ((c == '\t') || !iscntrl(c)))
static inline void
clean_ascii(char *buf, int sz)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz;
- while (ptr < end) {
- *(ptr++) ^= ASCII_XOR;
- }
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz;
+ while (ptr < end) {
+ *(ptr++) ^= ASCII_XOR;
+ }
}
static inline void
dump_ascii(const void *buf, int sz)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz;
- printf("\t");
- while (ptr < end) {
- uint8_t c = *(ptr++) ^ ASCII_XOR;
- if (c == '\n') {
- printf("\n\t");
- } else if (c == '\0') {
- printf("\n\t-----------------------------------\n\t");
- } else if (is_ok_ascii(c)) {
- printf("%c", c);
- } else {
- printf("?");
- }
- }
- printf("\n");
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz;
+ printf("\t");
+ while (ptr < end) {
+ uint8_t c = *(ptr++) ^ ASCII_XOR;
+ if (c == '\n') {
+ printf("\n\t");
+ } else if (c == '\0') {
+ printf("\n\t-----------------------------------\n\t");
+ } else if (is_ok_ascii(c)) {
+ printf("%c", c);
+ } else {
+ printf("?");
+ }
+ }
+ printf("\n");
}
static inline void
dump_hex_ascii(const void *buf, int sz, int level)
{
- uint8_t *ptr = (uint8_t *)buf;
- uint8_t *end = ptr + sz;
- uint8_t *ascii = ptr;
- int i = 0;
-
- printf("%s-----------------------------------------------\n", tab(level));
- printf("%s%d (0x%x) bytes\n", tab(level), sz, sz);
-
- while (ptr < end) {
- uint32_t d = 0;
-
- if (i % 4) {
- printf(" ");
- } else {
- printf("%s%06x: ", tab(level), (uint32_t)(ptr - (uint8_t *)buf));
- }
-
- d |= *(ptr++) << 0;
- d |= *(ptr++) << 8;
- d |= *(ptr++) << 16;
- d |= *(ptr++) << 24;
-
- printf("%08x", d);
-
- if ((i % 4) == 3) {
- int j;
- printf("\t|");
- for (j = 0; j < 16; j++) {
- uint8_t c = *(ascii++);
- c ^= ASCII_XOR;
- printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
- }
- printf("|\n");
- }
-
- i++;
- }
-
- if (i % 4) {
- for (int j = 4 - (i % 4); j > 0; j--) {
- printf(" ");
- }
- printf("\t|");
- while (ascii < end) {
- uint8_t c = *(ascii++);
- c ^= ASCII_XOR;
- printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
- }
- printf("|\n");
- }
+ uint8_t *ptr = (uint8_t *)buf;
+ uint8_t *end = ptr + sz;
+ uint8_t *ascii = ptr;
+ int i = 0;
+
+ printf("%s-----------------------------------------------\n", tab(level));
+ printf("%s%d (0x%x) bytes\n", tab(level), sz, sz);
+
+ while (ptr < end) {
+ uint32_t d = 0;
+
+ if (i % 4) {
+ printf(" ");
+ } else {
+ printf("%s%06x: ", tab(level), (uint32_t)(ptr - (uint8_t *)buf));
+ }
+
+ d |= *(ptr++) << 0;
+ d |= *(ptr++) << 8;
+ d |= *(ptr++) << 16;
+ d |= *(ptr++) << 24;
+
+ printf("%08x", d);
+
+ if ((i % 4) == 3) {
+ int j;
+ printf("\t|");
+ for (j = 0; j < 16; j++) {
+ uint8_t c = *(ascii++);
+ c ^= ASCII_XOR;
+ printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
+ }
+ printf("|\n");
+ }
+
+ i++;
+ }
+
+ if (i % 4) {
+ for (int j = 4 - (i % 4); j > 0; j--) {
+ printf(" ");
+ }
+ printf("\t|");
+ while (ascii < end) {
+ uint8_t c = *(ascii++);
+ c ^= ASCII_XOR;
+ printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
+ }
+ printf("|\n");
+ }
}
#endif /* __UTIL_H__ */