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 #include -#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; + 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; + /* 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 #include +#include 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 #include #include +#include +#include #include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include -#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(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), +// 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}, + {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), + 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_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), + 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}, + {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; + options = _options; + summary = options->summary; - /* in case we're decoding multiple files: */ - free(queryvals); - reset_regs(); - draw_count = 0; + /* 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 */ + /* 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"); - } + 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); + 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); + 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; - } - } + /* 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))); - } + if (gpuaddr && hostptr(gpuaddr)) { + printf("\t\tbase=%" PRIx64 ", offset=%" PRIu64 ", size=%u", + gpubaseaddr(gpuaddr), gpuaddr - gpubaseaddr(gpuaddr), + hostlen(gpubaseaddr(gpuaddr))); + } - printf("\n"); + 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); - } + 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); - } + 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; + 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")); + 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; - } + 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++; - } - } + 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"); + 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; + 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 = ""; - disasm_type = 0; - break; - } + 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 = ""; + 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); + 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); + /* 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, + TEX_SAMP = 1, + TEX_CONST, + TEX_MIPADDR, /* a3xx only */ + SHADER_PROG, + SHADER_CONST, - // image/ssbo state: - SSBO_0, - SSBO_1, - SSBO_2, + // image/ssbo state: + SSBO_0, + SSBO_1, + SSBO_2, - UBO, + UBO, - // unknown things, just to hexdumps: - UNKNOWN_DWORDS, - UNKNOWN_2DWORDS, - UNKNOWN_4DWORDS, + // 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) +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 }, - }; + 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; + *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) + 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 }, - }; + 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; + *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) +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]); + 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) +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]); + 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; + 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; - } - } + 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; + 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; - } - } + 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; + 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 (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); + 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; - } + 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"); + 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; - } + 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; - } - } + 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 (ext_src_addr) + contents = hostptr(ext_src_addr); + else + contents = is_64b() ? dwords + 3 : dwords + 2; - if (!contents) - return; + if (!contents) + return; - switch (state) { - case SHADER_PROG: { - const char *ext = NULL; + switch (state) { + case SHADER_PROG: { + const char *ext = NULL; - if (quiet(2)) - return; + if (quiet(2)) + return; - if (options->gpu_id >= 400) - num_unit *= 16; - else if (options->gpu_id >= 300) - num_unit *= 4; + 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"; - } + /* 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); + 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); + /* dump raw shader: */ + if (ext) + dump_shader(ext, contents, num_unit * 2 * 4); - break; - } - case SHADER_CONST: { - if (quiet(2)) - return; + break; + } + case SHADER_CONST: { + if (quiet(2)) + return; - /* uniforms/consts: - * - * note: num_unit seems to be # of pairs of dwords?? - */ + /* uniforms/consts: + * + * note: num_unit seems to be # of pairs of dwords?? + */ - if (options->gpu_id >= 400) - num_unit *= 2; + if (options->gpu_id >= 400) + num_unit *= 2; - dump_float(contents, num_unit*2, level+1); - dump_hex(contents, num_unit*2, level+1); + dump_float(contents, num_unit * 2, level + 1); + dump_hex(contents, num_unit * 2, level + 1); - break; - } - case TEX_MIPADDR: { - uint32_t *addrs = contents; + break; + } + case TEX_MIPADDR: { + uint32_t *addrs = contents; - if (quiet(2)) - return; + 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; + /* 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++) { + 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++) { + 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 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; - } + 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; + 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) +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??"; + 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 */ + /* 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; + /* 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); + /* 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; + /* 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; + /* 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 + /* 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); + /* 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); + 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) +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]); - } - } + 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]; + 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)); + /* 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]); + /* 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]; + dstval += type0_reg_vals[srcreg]; - dump_registers(val, &dstval, 1, level+1); - } else { - dump_registers(val, dwords+1, sizedwords-1, level+1); - } - break; - } + 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; + uint32_t i; + bool saved_summary = summary; + summary = false; - in_summary = true; + 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); - } - } + /* 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(); + clear_rewritten(); - in_summary = false; + in_summary = false; - draw_count++; - summary = saved_summary; + 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); + uint32_t num_indices = draw_indx_common(dwords, level); - assert(!is_64b()); + 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); - } - } - } + /* 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); + /* don't bother dumping registers for the dummy draw_indx's.. */ + if (num_indices > 0) + dump_register_summary(level); - needs_wfi = true; + 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; + 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()); + 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); - } + /* 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); + /* 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]; + 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); + 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"); + 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); + 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; + /* 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; + /* 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 (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]; + 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); - } - } + 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); + 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; + /* 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 (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 (!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; + 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; + /* '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); + /* 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])); + 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; + 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); - } + 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), + 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 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 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 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), + /* 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(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; + 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(dwords); + if (!dwords) { + printf("NULL cmd buffer!\n"); + return; + } - assert(ib < ARRAY_SIZE(draws)); - draws[ib] = 0; + assert(ib < ARRAY_SIZE(draws)); + draws[ib] = 0; - while (dwords_left > 0) { + while (dwords_left > 0) { - current_draw_count = draw_count; + 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; + /* 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 (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; - } - } + } 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; + dwords += count; + dwords_left -= count; + } - } - - if (dwords_left < 0) - printf("**** this ain't right!! dwords_left=%d\n", dwords_left); + 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 enum query_mode { - /* default mode, dump all queried regs on each draw: */ - QUERY_ALL = 0, + /* 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 were written + * since last draw: + */ + QUERY_WRITTEN, - /* only dump if any of the queried regs changed since - * last draw: - */ - QUERY_DELTA, + /* 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; + 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; + 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; + /* 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]; + /* 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 #include #include +#include +#include #include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include -#include "redump.h" -#include "disasm.h" -#include "script.h" -#include "io.h" -#include "rnnutil.h" -#include "pager.h" #include "buffers.h" #include "cffdec.h" +#include "disasm.h" +#include "io.h" +#include "pager.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 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 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; + enum debug_t debug = PRINT_RAW | PRINT_STATS; + int ret = -1; + int start = 0, end = 0x7ffffff, draw = -1; + int c; - interactive = isatty(STDOUT_FILENO); + interactive = isatty(STDOUT_FILENO); - options.color = interactive; + 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]); - } - } + 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); + disasm_a2xx_set_debug(debug); + disasm_a3xx_set_debug(debug); - if (interactive) { - pager_open(); - } + 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++; - } + 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 (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]); - } + 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(); + script_finish(); - if (interactive) { - pager_close(); - } + if (interactive) { + pager_close(); + } - return ret; + 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; + 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; + options.draw_filter = draw; - cffdec_init(&options); + cffdec_init(&options); - printf("Reading %s...\n", filename); + printf("Reading %s...\n", filename); - script_start_cmdstream(filename); + script_start_cmdstream(filename); - if (!strcmp(filename, "-")) - io = io_openfd(0); - else - io = io_open(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; - } + if (!io) { + fprintf(stderr, "could not open: %s\n", filename); + return -1; + } - struct { - unsigned int len; - uint64_t gpuaddr; - } gpuaddr = {0}; + struct { + unsigned int len; + uint64_t gpuaddr; + } gpuaddr = {0}; - while (true) { - uint32_t arr[2]; + while (true) { + uint32_t arr[2]; - ret = io_readn(io, arr, 8); - if (ret <= 0) - goto end; + 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; - } + while ((arr[0] == 0xffffffff) && (arr[1] == 0xffffffff)) { + ret = io_readn(io, arr, 8); + if (ret <= 0) + goto end; + } - type = arr[0]; - sz = arr[1]; + type = arr[0]; + sz = arr[1]; - if (sz < 0) { - ret = -1; - goto end; - } + if (sz < 0) { + ret = -1; + goto end; + } - free(buf); + free(buf); - needs_wfi = false; + needs_wfi = false; - buf = malloc(sz + 1); - ((char *)buf)[sz] = '\0'; - ret = io_readn(io, buf, sz); - if (ret < 0) - goto end; + 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; - } - } + 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 #include #include @@ -48,14 +47,13 @@ #include #include +#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(); + 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++; + /* 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; + uint32_t *buf = calloc(1, 4 * sizedwords); + int idx = 0; - while (*line != '\n') { - if (*line == 'z') { - buf[idx++] = 0; - line++; - continue; - } + 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++; - } + uint32_t accum = 0; + for (int i = 0; (i < 5) && (*line != '\n'); i++) { + accum *= 85; + accum += *line - '!'; + line++; + } - buf[idx++] = accum; - } + buf[idx++] = accum; + } - return buf; + 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; + 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; - } - } - } + /* 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); + 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; + 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; - } + 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); - } + 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"); + uint64_t rb_base = regval64("CP_RB_BASE"); - printf("got rb_base=%"PRIx64"\n", 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"); + 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; - } + /* 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); + 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(); + /* 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; + 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"); + 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 */ + /* 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) +#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); + /* 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); - } + 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); + unsigned cmdszdw = mod_add(ringbuffers[id].wptr, -rptr); - printf("got cmdszdw=%d\n", cmdszdw); - uint32_t *buf = malloc(cmdszdw * 4); + 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]; - } + 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); - } + 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); + 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); - } + 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; - } + 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); + uint32_t offset, value; + parseline(line, " - { offset: %x, value: %x }", &offset, &value); - printf("\t%08x", value); - dump_register_val(offset/4, value, 0); - } + 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++; + 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: */ - } - } + 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]); - } + 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; + 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]); - } + /* 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. - */ + /* 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; - } - } + 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 (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 (!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; + 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)); + 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.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); - } + 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. - */ + /* 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; + /* 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]; + /* 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; + /* 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; + /* 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. - */ + /* 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 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] */ + 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 unk1; + uint32_t padding2[7]; /* Mirrors of unk1 */ - uint32_t writer_second_block[6]; - uint32_t padding3[2]; + uint32_t writer_second_block[6]; + uint32_t padding3[2]; - uint32_t unk2[6]; - uint32_t padding4[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] */ + 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 unk3; + uint32_t padding6[7]; /* Mirrors of unk3 */ - uint32_t reader_second_block[6]; - uint32_t padding7[2]; + uint32_t reader_second_block[6]; + uint32_t padding7[2]; - uint32_t block_count[6]; - uint32_t padding[2]; + uint32_t block_count[6]; + uint32_t padding[2]; - uint32_t unk4; - uint32_t padding9[7]; /* Mirrors of unk4 */ - } data1; + 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)); + 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; + /* 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]; + /* 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); + 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); - } + /* 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]); + 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]); - } + 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]; + 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]; + 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); + 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]); + 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"); - } + 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; + 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); + 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; + /* 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_SQE_STAT")) + dump_cp_sqe_stat(buf); - if (!strcmp(name, "CP_UCODE_DBG_DATA")) - dump_cp_ucode_dbg(buf); + if (!strcmp(name, "CP_UCODE_DBG_DATA")) + dump_cp_ucode_dbg(buf); - if (!strcmp(name, "CP_MEMPOOL")) - dump_cp_mem_pool(buf); + if (!strcmp(name, "CP_MEMPOOL")) + dump_cp_mem_pool(buf); - if (dump) - dump_hex_ascii(buf, 4 * sizedwords, 1); + if (dump) + dump_hex_ascii(buf, 4 * sizedwords, 1); - free(buf); + free(buf); - continue; - } + continue; + } - printf("%s", line); - } + printf("%s", line); + } } /* @@ -875,47 +892,45 @@ decode_indexed_registers(void) static void decode_shader_blocks(void) { - char *type = NULL; - uint32_t sizedwords = 0; + 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); + 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; + /* 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 (!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); + if (dump) + dump_hex_ascii(buf, 4 * sizedwords, 1); - free(buf); + free(buf); - continue; - } + continue; + } - printf("%s", line); - } + printf("%s", line); + } - free(type); + free(type); } /* @@ -925,34 +940,33 @@ decode_shader_blocks(void) static void decode_debugbus(void) { - char *block = NULL; - uint32_t sizedwords = 0; + 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); + 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; + /* 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); + if (dump) + dump_hex_ascii(buf, 4 * sizedwords, 1); - free(buf); + free(buf); - continue; - } + continue; + } - printf("%s", line); - } + printf("%s", line); + } } /* @@ -962,52 +976,55 @@ decode_debugbus(void) static void decode(void) { - const char *line; + 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); + 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); + 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(); + 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(); - } - } + /* 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; + int c; - interactive = isatty(STDOUT_FILENO); - options.color = interactive; + interactive = isatty(STDOUT_FILENO); + options.color = interactive; - /* default to read from stdin: */ - in = stdin; + /* 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(); - } - } + 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); + disasm_a3xx_set_debug(PRINT_RAW); - if (interactive) { - pager_open(); - } + if (interactive) { + pager_open(); + } - atexit(cleanup); + atexit(cleanup); - decode(); - 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 */ +#include +#include #include #include -#include #include -#include -#include +#include #include #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; + struct io *io = calloc(1, sizeof(*io)); + int ret; - if (!io) - return NULL; + 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; - } + 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_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_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; - } + ret = archive_read_support_format_raw(io->a); + if (ret != ARCHIVE_OK) { + io_error(io); + return NULL; + } - return io; + 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 -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 #include #include +#include #include #include -#include #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]; + int fd[2]; - if (pipe(fd) < 0) { - fprintf(stderr, "Failed to create pager pipe: %m\n"); - exit(-1); - } + 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); - } + 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; + if (pager_pid == 0) { + const char *less_opts; - dup2(fd[0], STDIN_FILENO); - close(fd[0]); - close(fd[1]); + dup2(fd[0], STDIN_FILENO); + close(fd[0]); + close(fd[1]); - less_opts = "FRSMKX"; - setenv("LESS", less_opts, 1); + less_opts = "FRSMKX"; + setenv("LESS", less_opts, 1); - execlp("less", "less", NULL); + 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]); - } + } 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 +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include -#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; + 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"); + /* 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; + static char filename[256]; + int fd; - if (!dump_shaders) - return; + 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); - } + 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; + int i, sect_size; + uint8_t *ptr; - /* dump vertex shaders: */ - for (i = 0; i < 3; i++) { - struct vs_header *vs_hdr = next_sect(state, §_size); - struct constant *constants[32]; - int j, level = 0; + /* dump vertex shaders: */ + for (i = 0; i < 3; i++) { + struct vs_header *vs_hdr = next_sect(state, §_size); + struct constant *constants[32]; + int j, level = 0; - printf("\n"); + printf("\n"); - if (full_dump) { - printf("#######################################################\n"); - printf("######## VS%d HEADER: (size %d)\n", i, sect_size); - dump_hex((void *)vs_hdr, sect_size); - } + 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, §_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); - } - } + for (j = 0; j < (int)vs_hdr->unknown1 - 1; j++) { + constants[j] = next_sect(state, §_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, §_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); + ptr = next_sect(state, §_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, §_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->unknown9; j++) { + ptr = next_sect(state, §_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]); - } + for (j = 0; j < vs_hdr->unknown1 - 1; j++) { + free(constants[j]); + } - free(vs_hdr); - } + free(vs_hdr); + } - /* dump fragment shaders: */ - for (i = 0; i < 1; i++) { - struct fs_header *fs_hdr = next_sect(state, §_size); - struct constant *constants[32]; - int j, level = 0; + /* dump fragment shaders: */ + for (i = 0; i < 1; i++) { + struct fs_header *fs_hdr = next_sect(state, §_size); + struct constant *constants[32]; + int j, level = 0; - printf("\n"); + printf("\n"); - if (full_dump) { - printf("#######################################################\n"); - printf("######## FS%d HEADER: (size %d)\n", i, sect_size); - dump_hex((void *)fs_hdr, sect_size); - } + 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, §_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); - } - } + for (j = 0; j < fs_hdr->unknown1 - 1; j++) { + constants[j] = next_sect(state, §_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, §_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); + ptr = next_sect(state, §_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]); - } + for (j = 0; j < fs_hdr->unknown1 - 1; j++) { + free(constants[j]); + } - free(fs_hdr); - } + free(fs_hdr); + } } -static void dump_shaders_a3xx(struct state *state) +static void +dump_shaders_a3xx(struct state *state) { - int i, j; + 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; + /* 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); + 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, §_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, §_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; - } - } + 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"); + 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])); - } - } + 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); - } + 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; - } + 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); - } + 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; + /* 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); + 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; + 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, §_size); + 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, §_size); - if ((sect_size != 32) && (sect_size != 44)) { - /* end of constants: */ - instrs = ptr; - instrs_size = sect_size; - break; - } + 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; - } - } + dump_hex_ascii(ptr, sect_size, 0); + constants[nconsts++] = ptr; + } + } - printf("\n"); + 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])); - } - } + 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); - } + 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); - } + 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; + int i, sect_size; + uint8_t *ptr; - state->hdr = next_sect(state, §_size); + state->hdr = next_sect(state, §_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"); + 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, §_size); - if (full_dump) { - dump_hex_ascii(ptr, sect_size, 0); - } + /* there seems to be two 0xba5eba11's at the end of the header, possibly + * with some other stuff between them: + */ + ptr = next_sect(state, §_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, §_size); + for (i = 0; (i < state->hdr->num_attribs) && (state->sz > 0); i++) { + state->attribs[i] = next_sect(state, §_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, §_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, §_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); - } - } + 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, §_size); + for (i = 0; (i < state->hdr->num_uniforms) && (state->sz > 0); i++) { + state->uniforms[i] = next_sect(state, §_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, §_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, §_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 (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); - } - } + 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, §_size); + for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) { + state->samplers[i] = next_sect(state, §_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, §_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, §_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); - } + 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, §_size); + dump_hex_ascii(ptr, sect_size, 0); + } + } - // 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, §_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, §_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, §_size); + } - for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) { - state->varyings[i] = next_sect(state, §_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); + } + } - /* 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, §_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, §_size); + dump_hex_ascii(ptr, sect_size, 0); + } + } - 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); - } - } + /* 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, §_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, §_size); - dump_hex_ascii(ptr, sect_size, 0); - } - } + 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); + } + } - /* 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, §_size); + for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) { + state->uniformblocks[i].header = next_sect(state, §_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); - } - } + 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); + } - for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) { - state->uniformblocks[i].header = next_sect(state, §_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 *)); - 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); - } + 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, §_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*)); + 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, §_size); - 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, §_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); + } + } + } - 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, §_size); + if (gpu_id >= 300) { + dump_shaders_a3xx(state); + } else { + dump_shaders_a2xx(state); + } - 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 (!full_dump) + return; - if (gpu_id >= 300) { - dump_shaders_a3xx(state); - } else { - dump_shaders_a2xx(state); - } + /* dump ascii version of shader program: */ + ptr = next_sect(state, §_size); + printf("\n#######################################################\n"); + printf("######## SHADER SRC: (size=%d)\n", sect_size); + dump_ascii(ptr, sect_size); + free(ptr); - if (!full_dump) - return; - - /* dump ascii version of shader program: */ - ptr = next_sect(state, §_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, §_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); + /* dump remaining sections (there shouldn't be any): */ + while (state->sz > 0) { + ptr = next_sect(state, §_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; + 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: */ + /* 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; - } + 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; - } + 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); + disasm_a2xx_set_debug(debug); + disasm_a3xx_set_debug(debug); - infile = argv[1]; + infile = argv[1]; - io = io_open(infile); - if (!io) { - fprintf(stderr, "could not open: %s\n", infile); - return -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); + 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; + /* 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; - } + 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); - } - } + /* 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); + 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); + /* 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; - } - } + 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); + io_close(io); - return 0; + 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 #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include -#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; + uint32_t *ptr = buf; + uint8_t *ascii = buf; - for (unsigned i = 0; i < n; i++) { - uint32_t d = ptr[i]; + for (unsigned i = 0; i < n; i++) { + uint32_t d = ptr[i]; - if (dump_offsets) - printf("%08x:", (uint32_t)((char *)&ptr[i] - state->buf)); + 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("%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)); + 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]); + /* 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"); - } + 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); + 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); + /* 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); + 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; + /* 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); - } + 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; + 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); - } + 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; + 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; - } + /* 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--; + 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; + 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: */ + /* 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; - } + 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; - } + if (argc != 2) { + fprintf(stderr, "usage: pgmdump2 [--verbose] [--expand] [--full] " + "[--dump-offsets] [--raw] [--shaderdb] testlog.rd\n"); + return -1; + } - disasm_a3xx_set_debug(debug); + disasm_a3xx_set_debug(debug); - infile = argv[1]; + infile = argv[1]; - io = io_open(infile); - if (!io) { - fprintf(stderr, "could not open: %s\n", infile); - return -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); + 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; + /* 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; - } + 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); - } + /* 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); + 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); + /* 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; - } - } + 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); + io_close(io); - return 0; + 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 */ +#include #include +#include #include #include -#include #include -#include #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_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->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; + /* 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"); + 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; + 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; + 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 #include #include -#include #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 -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include -#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); + 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) +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; - } - + 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) +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; - } + 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) +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; + 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; - } + 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); + 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; + 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); + 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); - } - } + return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo); + } + } - printf("invalid member: %s\n", name); - return 0; + printf("invalid member: %s\n", name); + return 0; } -static int l_rnn_reg_meta_tostring(lua_State *L) +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; + 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) +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); + struct rnndoff *rnndoff = lua_touserdata(L, 1); + uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset); - regval <<= rnndoff->elem->typeinfo.shr; + regval <<= rnndoff->elem->typeinfo.shr; - lua_pushnumber(L, regval); - return 1; + 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 - // 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; + 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); + printf("%s-----------------------------------------------\n", tab(level)); + printf("%s%d (0x%x) bytes\n", tab(level), sz, sz); - while (ptr < end) { - uint32_t d = 0; + while (ptr < end) { + uint32_t d = 0; - if (i % 4) { - printf(" "); - } else { - printf("%s%06x: ", tab(level), (uint32_t)(ptr - (uint8_t *)buf)); - } + 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; + d |= *(ptr++) << 0; + d |= *(ptr++) << 8; + d |= *(ptr++) << 16; + d |= *(ptr++) << 24; - printf("%08x", d); + 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"); - } + 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++; - } + 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"); - } + 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__ */