freedreno/decode: Re-indent

clang-format -fallback-style=none --style=file -i src/freedreno/decode/*.[ch]

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10293>
This commit is contained in:
Rob Clark 2021-04-16 11:25:06 -07:00 committed by Marge Bot
parent 3894bc9664
commit 45856c5fbc
18 changed files with 5391 additions and 5216 deletions

View File

@ -90,6 +90,7 @@ ForEachMacros:
- foreach_batch
- hash_table_foreach
- set_foreach
- foreach_line_in_section
IncludeBlocks: Preserve
IncludeCategories:

View File

@ -29,143 +29,148 @@
#include <assert.h>
#include <stdlib.h>
#include "buffers.h"
#include "util/rb_tree.h"
#include "buffers.h"
struct buffer {
struct rb_node node;
void *hostptr;
unsigned int len;
uint64_t gpuaddr;
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;
}

View File

@ -24,12 +24,12 @@
#ifndef __BUFFERS_H__
#define __BUFFERS_H__
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
uint64_t gpuaddr(void *hostptr);
uint64_t gpubaseaddr(uint64_t gpuaddr);
void * hostptr(uint64_t gpuaddr);
void *hostptr(uint64_t gpuaddr);
unsigned hostlen(uint64_t gpuaddr);
bool has_dumped(uint64_t gpuaddr, unsigned enable_mask);
@ -37,7 +37,7 @@ void reset_buffers(void);
void add_buffer(uint64_t gpuaddr, unsigned int len, void *hostptr);
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#endif /* __BUFFERS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -27,57 +27,57 @@
#include <stdbool.h>
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__ */

View File

@ -24,33 +24,32 @@
#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#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;
}

File diff suppressed because it is too large Load Diff

View File

@ -26,138 +26,145 @@
* Rob Clark <robclark@freedesktop.org>
*/
#include <archive.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <archive.h>
#include <sys/types.h>
#include <archive_entry.h>
#include "io.h"
struct io {
struct archive *a;
struct archive_entry *entry;
unsigned offset;
struct archive *a;
struct archive_entry *entry;
unsigned offset;
};
static void io_error(struct io *io)
static void
io_error(struct io *io)
{
fprintf(stderr, "%s\n", archive_error_string(io->a));
io_close(io);
fprintf(stderr, "%s\n", archive_error_string(io->a));
io_close(io);
}
static struct io * io_new(void)
static struct io *
io_new(void)
{
struct io *io = calloc(1, sizeof(*io));
int ret;
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 <assert.h>
int io_readn(struct io *io, void *buf, int nbytes)
int
io_readn(struct io *io, void *buf, int nbytes)
{
char *ptr = buf;
int ret = 0;
while (nbytes > 0) {
int n = archive_read_data(io->a, ptr, nbytes);
if (n < 0) {
fprintf(stderr, "%s\n", archive_error_string(io->a));
return n;
}
if (n == 0)
break;
ptr += n;
nbytes -= n;
ret += n;
io->offset += n;
}
return ret;
char *ptr = buf;
int ret = 0;
while (nbytes > 0) {
int n = archive_read_data(io->a, ptr, nbytes);
if (n < 0) {
fprintf(stderr, "%s\n", archive_error_string(io->a));
return n;
}
if (n == 0)
break;
ptr += n;
nbytes -= n;
ret += n;
io->offset += n;
}
return ret;
}

View File

@ -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_ */

View File

@ -27,73 +27,72 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "pager.h"
static pid_t pager_pid;
static void
pager_death(int n)
{
exit(0);
exit(0);
}
void
pager_open(void)
{
int fd[2];
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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -36,550 +36,569 @@
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stddef.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "redump.h"
#include "disasm.h"
#include "io.h"
#include "redump.h"
#include "util.h"
const char *infile;
static int dump_full = 0;
static int dump_offsets = 0;
static int gpu_id = 320;
static int shaderdb = 0; /* output shaderdb style traces to stderr */
static int shaderdb = 0; /* output shaderdb style traces to stderr */
struct state {
char *buf;
int sz;
int lvl;
char *buf;
int sz;
int lvl;
/* current shader_info section, some offsets calculated relative to
* this, rather than relative to start of buffer.
*/
void *shader;
/* current shader_info section, some offsets calculated relative to
* this, rather than relative to start of buffer.
*/
void *shader;
/* size of each entry within a shader_descriptor_blk: */
int desc_size;
/* size of each entry within a shader_descriptor_blk: */
int desc_size;
const char *shader_type;
int full_regs;
int half_regs;
const char *shader_type;
int full_regs;
int half_regs;
};
#define PACKED __attribute__((__packed__))
#define OFF(field) do { \
if (dump_offsets) \
printf("%08x: ", (uint32_t)((char *)&field - state->buf));\
} while (0)
#define OFF(field) \
do { \
if (dump_offsets) \
printf("%08x: ", (uint32_t)((char *)&field - state->buf)); \
} while (0)
/* decode field as hex */
#define X(s, field) do { \
OFF(s->field); \
printf("%s%12s:\t0x%x\n", tab(state->lvl), #field, s->field); \
} while (0)
#define X(s, field) \
do { \
OFF(s->field); \
printf("%s%12s:\t0x%x\n", tab(state->lvl), #field, s->field); \
} while (0)
/* decode field as digit */
#define D(s, field) do { \
OFF(s->field); \
printf("%s%12s:\t%u\n", tab(state->lvl), #field, s->field); \
} while (0)
#define D(s, field) \
do { \
OFF(s->field); \
printf("%s%12s:\t%u\n", tab(state->lvl), #field, s->field); \
} while (0)
/* decode field as float/hex */
#define F(s, field) do { \
OFF(s->field); \
printf("%s%12s:\t%f (0x%0x)\n", tab(state->lvl), #field, \
d2f(s->field), s->field); \
} while (0)
#define F(s, field) \
do { \
OFF(s->field); \
printf("%s%12s:\t%f (0x%0x)\n", tab(state->lvl), #field, d2f(s->field), \
s->field); \
} while (0)
/* decode field as register: (type is 'r' or 'c') */
#define R(s, field, type) do { \
OFF(s->field); \
printf("%s%12s:\t%c%u.%c\n", tab(state->lvl), #field, type, \
(s->field >> 2), "xyzw"[s->field & 0x3]); \
} while (0)
#define R(s, field, type) \
do { \
OFF(s->field); \
printf("%s%12s:\t%c%u.%c\n", tab(state->lvl), #field, type, \
(s->field >> 2), "xyzw"[s->field & 0x3]); \
} while (0)
/* decode inline string (presumably null terminated?) */
#define S(s, field) do { \
OFF(s->field); \
printf("%s%12s:\t%s\n", tab(state->lvl), #field, s->field); \
} while (0)
#define S(s, field) \
do { \
OFF(s->field); \
printf("%s%12s:\t%s\n", tab(state->lvl), #field, s->field); \
} while (0)
/* decode string-table string */
#define T(s, field) TODO
#define T(s, field) TODO
/* decode field as unknown */
#define U(s, start, end) \
dump_unknown(state, s->unk_ ## start ## _ ## end, 0x ## start, (4 + 0x ## end - 0x ## start) / 4)
#define U(s, start, end) \
dump_unknown(state, s->unk_##start##_##end, 0x##start, \
(4 + 0x##end - 0x##start) / 4)
/* decode field as offset to other section */
#define O(s, field, type) do { \
X(s, field); \
assert(s->field < state->sz); \
void *_p = &state->buf[s->field]; \
state->lvl++; \
decode_ ## type (state, _p); \
state->lvl--; \
} while (0)
#define O(s, field, type) \
do { \
X(s, field); \
assert(s->field < state->sz); \
void *_p = &state->buf[s->field]; \
state->lvl++; \
decode_##type(state, _p); \
state->lvl--; \
} while (0)
struct shader_info;
static void decode_shader_info(struct state *state, struct shader_info *info);
static void dump_unknown(struct state *state, void *buf, unsigned start, unsigned n)
static void
dump_unknown(struct state *state, void *buf, unsigned start, unsigned n)
{
uint32_t *ptr = buf;
uint8_t *ascii = buf;
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;
}

View File

@ -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))

View File

@ -26,183 +26,198 @@
* Rob Clark <robclark@freedesktop.org>
*/
#include <assert.h>
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "rnnutil.h"
static struct rnndomain *finddom(struct rnn *rnn, uint32_t regbase)
static struct rnndomain *
finddom(struct rnn *rnn, uint32_t regbase)
{
if (rnndec_checkaddr(rnn->vc, rnn->dom[0], regbase, 0))
return rnn->dom[0];
return rnn->dom[1];
if (rnndec_checkaddr(rnn->vc, rnn->dom[0], regbase, 0))
return rnn->dom[0];
return rnn->dom[1];
}
void _rnn_init(struct rnn *rnn, int nocolor)
void
_rnn_init(struct rnn *rnn, int nocolor)
{
rnn_init();
rnn_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;
}
}

View File

@ -29,24 +29,24 @@
#ifndef RNNUTIL_H_
#define RNNUTIL_H_
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "rnn.h"
#include "rnndec.h"
struct rnn {
struct rnndb *db;
struct rnndeccontext *vc, *vc_nocolor;
struct rnndomain *dom[2];
const char *variant;
struct rnndb *db;
struct rnndeccontext *vc, *vc_nocolor;
struct rnndomain *dom[2];
const char *variant;
};
union rnndecval {
uint32_t u;
int32_t i;
float f;
uint32_t u;
int32_t i;
float f;
};
void _rnn_init(struct rnn *rnn, int nocolor);
@ -61,6 +61,6 @@ const char *rnn_enumname(struct rnn *rnn, const char *name, uint32_t val);
struct rnndelem *rnn_regelem(struct rnn *rnn, const char *name);
struct rnndelem *rnn_regoff(struct rnn *rnn, uint32_t offset);
enum rnnttype rnn_decodelem(struct rnn *rnn, struct rnntypeinfo *info,
uint32_t regval, union rnndecval *val);
uint32_t regval, union rnndecval *val);
#endif /* RNNUTIL_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,6 @@
#include <stdint.h>
// XXX make script support optional
#define ENABLE_SCRIPTING 1
@ -53,7 +52,8 @@ struct rnn;
struct rnndomain;
__attribute__((weak))
void script_packet(uint32_t *dwords, uint32_t sizedwords,
struct rnn *rnn, struct rnndomain *dom);
struct rnn *rnn,
struct rnndomain *dom);
/* maybe at some point it is interesting to add additional script
* hooks for CP_EVENT_WRITE, etc?
@ -72,5 +72,4 @@ void script_finish(void);
// TODO no-op stubs..
#endif
#endif /* SCRIPT_H_ */

View File

@ -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__ */