xref: /aosp_15_r20/external/mesa3d/src/freedreno/decode/pgmdump2.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2018 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker /*
7*61046927SAndroid Build Coastguard Worker  * Decoder for "new" GL_OES_get_program_binary format.
8*61046927SAndroid Build Coastguard Worker  *
9*61046927SAndroid Build Coastguard Worker  * Overall structure is:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  *   - header at top, contains, amongst other things, offsets of
12*61046927SAndroid Build Coastguard Worker  *     per shader stage sections.
13*61046927SAndroid Build Coastguard Worker  *   - per shader stage section (shader_info) starts with a header,
14*61046927SAndroid Build Coastguard Worker  *     followed by a variably length list of descriptors.  Each
15*61046927SAndroid Build Coastguard Worker  *     descriptor has a type/count/size plus offset from the start
16*61046927SAndroid Build Coastguard Worker  *     of shader_info section where the data is found
17*61046927SAndroid Build Coastguard Worker  */
18*61046927SAndroid Build Coastguard Worker 
19*61046927SAndroid Build Coastguard Worker #include <assert.h>
20*61046927SAndroid Build Coastguard Worker #include <ctype.h>
21*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
22*61046927SAndroid Build Coastguard Worker #include <stddef.h>
23*61046927SAndroid Build Coastguard Worker #include <stdint.h>
24*61046927SAndroid Build Coastguard Worker #include <stdio.h>
25*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
26*61046927SAndroid Build Coastguard Worker #include <string.h>
27*61046927SAndroid Build Coastguard Worker #include <unistd.h>
28*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
29*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #include "disasm.h"
32*61046927SAndroid Build Coastguard Worker #include "io.h"
33*61046927SAndroid Build Coastguard Worker #include "redump.h"
34*61046927SAndroid Build Coastguard Worker #include "util.h"
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker const char *infile;
37*61046927SAndroid Build Coastguard Worker static int dump_full = 0;
38*61046927SAndroid Build Coastguard Worker static int dump_offsets = 0;
39*61046927SAndroid Build Coastguard Worker static int gpu_id = 320;
40*61046927SAndroid Build Coastguard Worker static int shaderdb = 0; /* output shaderdb style traces to stderr */
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker struct state {
43*61046927SAndroid Build Coastguard Worker    char *buf;
44*61046927SAndroid Build Coastguard Worker    int sz;
45*61046927SAndroid Build Coastguard Worker    int lvl;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    /* current shader_info section, some offsets calculated relative to
48*61046927SAndroid Build Coastguard Worker     * this, rather than relative to start of buffer.
49*61046927SAndroid Build Coastguard Worker     */
50*61046927SAndroid Build Coastguard Worker    void *shader;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    /* size of each entry within a shader_descriptor_blk: */
53*61046927SAndroid Build Coastguard Worker    int desc_size;
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    const char *shader_type;
56*61046927SAndroid Build Coastguard Worker    int full_regs;
57*61046927SAndroid Build Coastguard Worker    int half_regs;
58*61046927SAndroid Build Coastguard Worker };
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker #define PACKED __attribute__((__packed__))
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker #define OFF(field)                                                             \
63*61046927SAndroid Build Coastguard Worker    do {                                                                        \
64*61046927SAndroid Build Coastguard Worker       if (dump_offsets)                                                        \
65*61046927SAndroid Build Coastguard Worker          printf("%08x: ", (uint32_t)((char *)&field - state->buf));            \
66*61046927SAndroid Build Coastguard Worker    } while (0)
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker /* decode field as hex */
69*61046927SAndroid Build Coastguard Worker #define X(s, field)                                                            \
70*61046927SAndroid Build Coastguard Worker    do {                                                                        \
71*61046927SAndroid Build Coastguard Worker       OFF(s->field);                                                           \
72*61046927SAndroid Build Coastguard Worker       printf("%s%12s:\t0x%x\n", tab(state->lvl), #field, s->field);            \
73*61046927SAndroid Build Coastguard Worker    } while (0)
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker /* decode field as digit */
76*61046927SAndroid Build Coastguard Worker #define D(s, field)                                                            \
77*61046927SAndroid Build Coastguard Worker    do {                                                                        \
78*61046927SAndroid Build Coastguard Worker       OFF(s->field);                                                           \
79*61046927SAndroid Build Coastguard Worker       printf("%s%12s:\t%u\n", tab(state->lvl), #field, s->field);              \
80*61046927SAndroid Build Coastguard Worker    } while (0)
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker /* decode field as float/hex */
83*61046927SAndroid Build Coastguard Worker #define F(s, field)                                                            \
84*61046927SAndroid Build Coastguard Worker    do {                                                                        \
85*61046927SAndroid Build Coastguard Worker       OFF(s->field);                                                           \
86*61046927SAndroid Build Coastguard Worker       printf("%s%12s:\t%f (0x%0x)\n", tab(state->lvl), #field, uif(s->field),  \
87*61046927SAndroid Build Coastguard Worker              s->field);                                                        \
88*61046927SAndroid Build Coastguard Worker    } while (0)
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker /* decode field as register: (type is 'r' or 'c') */
91*61046927SAndroid Build Coastguard Worker #define R(s, field, type)                                                      \
92*61046927SAndroid Build Coastguard Worker    do {                                                                        \
93*61046927SAndroid Build Coastguard Worker       OFF(s->field);                                                           \
94*61046927SAndroid Build Coastguard Worker       printf("%s%12s:\t%c%u.%c\n", tab(state->lvl), #field, type,              \
95*61046927SAndroid Build Coastguard Worker              (s->field >> 2), "xyzw"[s->field & 0x3]);                         \
96*61046927SAndroid Build Coastguard Worker    } while (0)
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker /* decode inline string (presumably null terminated?) */
99*61046927SAndroid Build Coastguard Worker #define S(s, field)                                                            \
100*61046927SAndroid Build Coastguard Worker    do {                                                                        \
101*61046927SAndroid Build Coastguard Worker       OFF(s->field);                                                           \
102*61046927SAndroid Build Coastguard Worker       printf("%s%12s:\t%s\n", tab(state->lvl), #field, s->field);              \
103*61046927SAndroid Build Coastguard Worker    } while (0)
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker /* decode string-table string */
106*61046927SAndroid Build Coastguard Worker #define T(s, field) TODO
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker /* decode field as unknown */
109*61046927SAndroid Build Coastguard Worker #define U(s, start, end)                                                       \
110*61046927SAndroid Build Coastguard Worker    dump_unknown(state, s->unk_##start##_##end, 0x##start,                      \
111*61046927SAndroid Build Coastguard Worker                 (4 + 0x##end - 0x##start) / 4)
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker /* decode field as offset to other section */
114*61046927SAndroid Build Coastguard Worker #define O(s, field, type)                                                      \
115*61046927SAndroid Build Coastguard Worker    do {                                                                        \
116*61046927SAndroid Build Coastguard Worker       X(s, field);                                                             \
117*61046927SAndroid Build Coastguard Worker       assert(s->field < state->sz);                                            \
118*61046927SAndroid Build Coastguard Worker       void *_p = &state->buf[s->field];                                        \
119*61046927SAndroid Build Coastguard Worker       state->lvl++;                                                            \
120*61046927SAndroid Build Coastguard Worker       decode_##type(state, _p);                                                \
121*61046927SAndroid Build Coastguard Worker       state->lvl--;                                                            \
122*61046927SAndroid Build Coastguard Worker    } while (0)
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker struct shader_info;
125*61046927SAndroid Build Coastguard Worker static void decode_shader_info(struct state *state, struct shader_info *info);
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker static void
dump_unknown(struct state * state,void * buf,unsigned start,unsigned n)128*61046927SAndroid Build Coastguard Worker dump_unknown(struct state *state, void *buf, unsigned start, unsigned n)
129*61046927SAndroid Build Coastguard Worker {
130*61046927SAndroid Build Coastguard Worker    uint32_t *ptr = buf;
131*61046927SAndroid Build Coastguard Worker    uint8_t *ascii = buf;
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < n; i++) {
134*61046927SAndroid Build Coastguard Worker       uint32_t d = ptr[i];
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker       if (dump_offsets)
137*61046927SAndroid Build Coastguard Worker          printf("%08x:", (uint32_t)((char *)&ptr[i] - state->buf));
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker       printf("%s        %04x:\t%08x", tab(state->lvl), start + i * 4, d);
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker       printf("\t|");
142*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < 4; j++) {
143*61046927SAndroid Build Coastguard Worker          uint8_t c = *(ascii++);
144*61046927SAndroid Build Coastguard Worker          printf("%c", (isascii(c) && !iscntrl(c)) ? c : '.');
145*61046927SAndroid Build Coastguard Worker       }
146*61046927SAndroid Build Coastguard Worker       printf("|\t%f", uif(d));
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker       /* TODO maybe scan for first non-null and non-ascii char starting from
149*61046927SAndroid Build Coastguard Worker        * end of shader binary to (roughly) establish the start of the string
150*61046927SAndroid Build Coastguard Worker        * table.. that would be a bit better filter for deciding if something
151*61046927SAndroid Build Coastguard Worker        * might be a pointer into the string table.  Also, the previous char
152*61046927SAndroid Build Coastguard Worker        * to what it points to should probably be null.
153*61046927SAndroid Build Coastguard Worker        */
154*61046927SAndroid Build Coastguard Worker       if ((d < state->sz) && isascii(state->buf[d]) &&
155*61046927SAndroid Build Coastguard Worker           (strlen(&state->buf[d]) > 2) && isascii(state->buf[d + 1]))
156*61046927SAndroid Build Coastguard Worker          printf("\t<== %s", &state->buf[d]);
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker       printf("\n");
159*61046927SAndroid Build Coastguard Worker    }
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker struct PACKED header {
163*61046927SAndroid Build Coastguard Worker    uint32_t version; /* I guess, always b10bcace ? */
164*61046927SAndroid Build Coastguard Worker    uint32_t unk_0004_0014[5];
165*61046927SAndroid Build Coastguard Worker    uint32_t size;
166*61046927SAndroid Build Coastguard Worker    uint32_t size2; /* just to be sure? */
167*61046927SAndroid Build Coastguard Worker    uint32_t unk_0020_0020[1];
168*61046927SAndroid Build Coastguard Worker    uint32_t
169*61046927SAndroid Build Coastguard Worker       chksum; /* I guess?  Small changes seem to result in big diffs here */
170*61046927SAndroid Build Coastguard Worker    uint32_t unk_0028_0050[11];
171*61046927SAndroid Build Coastguard Worker    uint32_t fs_info; /* offset of FS shader_info section */
172*61046927SAndroid Build Coastguard Worker    uint32_t unk_0058_0090[15];
173*61046927SAndroid Build Coastguard Worker    uint32_t vs_info; /* offset of VS shader_info section */
174*61046927SAndroid Build Coastguard Worker    uint32_t unk_0098_00b0[7];
175*61046927SAndroid Build Coastguard Worker    uint32_t vs_info2; /* offset of VS shader_info section (again?) */
176*61046927SAndroid Build Coastguard Worker    uint32_t unk_00b8_0110[23];
177*61046927SAndroid Build Coastguard Worker    uint32_t bs_info; /* offset of binning shader_info section */
178*61046927SAndroid Build Coastguard Worker };
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker static void
decode_header(struct state * state,struct header * hdr)181*61046927SAndroid Build Coastguard Worker decode_header(struct state *state, struct header *hdr)
182*61046927SAndroid Build Coastguard Worker {
183*61046927SAndroid Build Coastguard Worker    X(hdr, version);
184*61046927SAndroid Build Coastguard Worker    U(hdr, 0004, 0014);
185*61046927SAndroid Build Coastguard Worker    X(hdr, size);
186*61046927SAndroid Build Coastguard Worker    X(hdr, size2);
187*61046927SAndroid Build Coastguard Worker    U(hdr, 0020, 0020);
188*61046927SAndroid Build Coastguard Worker    X(hdr, chksum);
189*61046927SAndroid Build Coastguard Worker    U(hdr, 0028, 0050);
190*61046927SAndroid Build Coastguard Worker    state->shader_type = "FRAG";
191*61046927SAndroid Build Coastguard Worker    O(hdr, fs_info, shader_info);
192*61046927SAndroid Build Coastguard Worker    U(hdr, 0058, 0090);
193*61046927SAndroid Build Coastguard Worker    state->shader_type = "VERT";
194*61046927SAndroid Build Coastguard Worker    O(hdr, vs_info, shader_info);
195*61046927SAndroid Build Coastguard Worker    U(hdr, 0098, 00b0);
196*61046927SAndroid Build Coastguard Worker    assert(hdr->vs_info ==
197*61046927SAndroid Build Coastguard Worker           hdr->vs_info2); /* not sure what this if it is ever different */
198*61046927SAndroid Build Coastguard Worker    X(hdr, vs_info2);
199*61046927SAndroid Build Coastguard Worker    U(hdr, 00b8, 0110);
200*61046927SAndroid Build Coastguard Worker    state->shader_type = "BVERT";
201*61046927SAndroid Build Coastguard Worker    O(hdr, bs_info, shader_info);
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    /* not sure how much of the rest of contents before start of fs_info
204*61046927SAndroid Build Coastguard Worker     * is the header, vs other things.. just dump it all as unknown for
205*61046927SAndroid Build Coastguard Worker     * now:
206*61046927SAndroid Build Coastguard Worker     */
207*61046927SAndroid Build Coastguard Worker    dump_unknown(state, (void *)hdr + sizeof(*hdr), sizeof(*hdr),
208*61046927SAndroid Build Coastguard Worker                 (hdr->fs_info - sizeof(*hdr)) / 4);
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker struct PACKED shader_entry_point {
212*61046927SAndroid Build Coastguard Worker    /* entry point name, ie. "main" of TBD length, followed by unknown */
213*61046927SAndroid Build Coastguard Worker    char name[8];
214*61046927SAndroid Build Coastguard Worker };
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker static void
decode_shader_entry_point(struct state * state,struct shader_entry_point * e)217*61046927SAndroid Build Coastguard Worker decode_shader_entry_point(struct state *state, struct shader_entry_point *e)
218*61046927SAndroid Build Coastguard Worker {
219*61046927SAndroid Build Coastguard Worker    S(e, name);
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker struct PACKED shader_config {
223*61046927SAndroid Build Coastguard Worker    uint32_t unk_0000_0008[3];
224*61046927SAndroid Build Coastguard Worker    uint32_t full_regs;
225*61046927SAndroid Build Coastguard Worker    uint32_t half_regs;
226*61046927SAndroid Build Coastguard Worker };
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker static void
decode_shader_config(struct state * state,struct shader_config * cfg)229*61046927SAndroid Build Coastguard Worker decode_shader_config(struct state *state, struct shader_config *cfg)
230*61046927SAndroid Build Coastguard Worker {
231*61046927SAndroid Build Coastguard Worker    U(cfg, 0000, 0008);
232*61046927SAndroid Build Coastguard Worker    D(cfg, full_regs);
233*61046927SAndroid Build Coastguard Worker    D(cfg, half_regs);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    state->full_regs = cfg->full_regs;
236*61046927SAndroid Build Coastguard Worker    state->half_regs = cfg->half_regs;
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker    /* dump reset of unknown (size differs btwn versions) */
239*61046927SAndroid Build Coastguard Worker    dump_unknown(state, (void *)cfg + sizeof(*cfg), sizeof(*cfg),
240*61046927SAndroid Build Coastguard Worker                 (state->desc_size - sizeof(*cfg)) / 4);
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker struct PACKED shader_io_block {
244*61046927SAndroid Build Coastguard Worker    /* name of TBD length followed by unknown.. 42 dwords total */
245*61046927SAndroid Build Coastguard Worker    char name[20];
246*61046927SAndroid Build Coastguard Worker    uint32_t unk_0014_00a4[37];
247*61046927SAndroid Build Coastguard Worker };
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker static void
decode_shader_io_block(struct state * state,struct shader_io_block * io)250*61046927SAndroid Build Coastguard Worker decode_shader_io_block(struct state *state, struct shader_io_block *io)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker    S(io, name);
253*61046927SAndroid Build Coastguard Worker    U(io, 0014, 00a4);
254*61046927SAndroid Build Coastguard Worker }
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker struct PACKED shader_constant_block {
257*61046927SAndroid Build Coastguard Worker    uint32_t value;
258*61046927SAndroid Build Coastguard Worker    uint32_t unk_0004_000c[3];
259*61046927SAndroid Build Coastguard Worker    uint32_t regid;
260*61046927SAndroid Build Coastguard Worker    uint32_t unk_0014_0024[5];
261*61046927SAndroid Build Coastguard Worker };
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker static void
decode_shader_constant_block(struct state * state,struct shader_constant_block * c)264*61046927SAndroid Build Coastguard Worker decode_shader_constant_block(struct state *state,
265*61046927SAndroid Build Coastguard Worker                              struct shader_constant_block *c)
266*61046927SAndroid Build Coastguard Worker {
267*61046927SAndroid Build Coastguard Worker    F(c, value);
268*61046927SAndroid Build Coastguard Worker    U(c, 0004, 000c);
269*61046927SAndroid Build Coastguard Worker    R(c, regid, 'c');
270*61046927SAndroid Build Coastguard Worker    U(c, 0014, 0024);
271*61046927SAndroid Build Coastguard Worker }
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker enum {
274*61046927SAndroid Build Coastguard Worker    ENTRY_POINT = 0,   /* shader_entry_point */
275*61046927SAndroid Build Coastguard Worker    SHADER_CONFIG = 1, /* XXX placeholder name */
276*61046927SAndroid Build Coastguard Worker    SHADER_INPUT = 2,  /* shader_io_block */
277*61046927SAndroid Build Coastguard Worker    SHADER_OUTPUT = 3, /* shader_io_block */
278*61046927SAndroid Build Coastguard Worker    CONSTANTS = 6,     /* shader_constant_block */
279*61046927SAndroid Build Coastguard Worker    INTERNAL = 8,      /* internal input, like bary.f coord */
280*61046927SAndroid Build Coastguard Worker    SHADER = 10,
281*61046927SAndroid Build Coastguard Worker } shader_info_block_type;
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker /* Refers to location of some type of records, with an offset relative to
284*61046927SAndroid Build Coastguard Worker  * start of shader_info block.
285*61046927SAndroid Build Coastguard Worker  */
286*61046927SAndroid Build Coastguard Worker struct PACKED shader_descriptor_block {
287*61046927SAndroid Build Coastguard Worker    uint32_t type;   /* block type */
288*61046927SAndroid Build Coastguard Worker    uint32_t offset; /* offset (relative to start of shader_info block) */
289*61046927SAndroid Build Coastguard Worker    uint32_t size;   /* size in bytes */
290*61046927SAndroid Build Coastguard Worker    uint32_t count;  /* number of records */
291*61046927SAndroid Build Coastguard Worker    uint32_t unk_0010_0010[1];
292*61046927SAndroid Build Coastguard Worker };
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker static void
decode_shader_descriptor_block(struct state * state,struct shader_descriptor_block * blk)295*61046927SAndroid Build Coastguard Worker decode_shader_descriptor_block(struct state *state,
296*61046927SAndroid Build Coastguard Worker                                struct shader_descriptor_block *blk)
297*61046927SAndroid Build Coastguard Worker {
298*61046927SAndroid Build Coastguard Worker    D(blk, type);
299*61046927SAndroid Build Coastguard Worker    X(blk, offset);
300*61046927SAndroid Build Coastguard Worker    D(blk, size);
301*61046927SAndroid Build Coastguard Worker    D(blk, count);
302*61046927SAndroid Build Coastguard Worker    U(blk, 0010, 0010);
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    /* offset relative to current shader block: */
305*61046927SAndroid Build Coastguard Worker    void *ptr = state->shader + blk->offset;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    if (blk->count == 0) {
308*61046927SAndroid Build Coastguard Worker       assert(blk->size == 0);
309*61046927SAndroid Build Coastguard Worker    } else {
310*61046927SAndroid Build Coastguard Worker       assert((blk->size % blk->count) == 0);
311*61046927SAndroid Build Coastguard Worker    }
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    state->desc_size = blk->size / blk->count;
314*61046927SAndroid Build Coastguard Worker    state->lvl++;
315*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < blk->count; i++) {
316*61046927SAndroid Build Coastguard Worker       switch (blk->type) {
317*61046927SAndroid Build Coastguard Worker       case ENTRY_POINT:
318*61046927SAndroid Build Coastguard Worker          printf("%sentry point %u:\n", tab(state->lvl - 1), i);
319*61046927SAndroid Build Coastguard Worker          decode_shader_entry_point(state, ptr);
320*61046927SAndroid Build Coastguard Worker          break;
321*61046927SAndroid Build Coastguard Worker       case SHADER_CONFIG:
322*61046927SAndroid Build Coastguard Worker          printf("%sconfig %u:\n", tab(state->lvl - 1), i);
323*61046927SAndroid Build Coastguard Worker          decode_shader_config(state, ptr);
324*61046927SAndroid Build Coastguard Worker          break;
325*61046927SAndroid Build Coastguard Worker       case SHADER_INPUT:
326*61046927SAndroid Build Coastguard Worker          printf("%sinput %u:\n", tab(state->lvl - 1), i);
327*61046927SAndroid Build Coastguard Worker          decode_shader_io_block(state, ptr);
328*61046927SAndroid Build Coastguard Worker          break;
329*61046927SAndroid Build Coastguard Worker       case SHADER_OUTPUT:
330*61046927SAndroid Build Coastguard Worker          printf("%soutput %u:\n", tab(state->lvl - 1), i);
331*61046927SAndroid Build Coastguard Worker          decode_shader_io_block(state, ptr);
332*61046927SAndroid Build Coastguard Worker          break;
333*61046927SAndroid Build Coastguard Worker       case INTERNAL:
334*61046927SAndroid Build Coastguard Worker          printf("%sinternal input %u:\n", tab(state->lvl - 1), i);
335*61046927SAndroid Build Coastguard Worker          decode_shader_io_block(state, ptr);
336*61046927SAndroid Build Coastguard Worker          break;
337*61046927SAndroid Build Coastguard Worker       case CONSTANTS:
338*61046927SAndroid Build Coastguard Worker          printf("%sconstant %u:\n", tab(state->lvl - 1), i);
339*61046927SAndroid Build Coastguard Worker          decode_shader_constant_block(state, ptr);
340*61046927SAndroid Build Coastguard Worker          break;
341*61046927SAndroid Build Coastguard Worker       case SHADER: {
342*61046927SAndroid Build Coastguard Worker          struct shader_stats stats;
343*61046927SAndroid Build Coastguard Worker          printf("%sshader %u:\n", tab(state->lvl - 1), i);
344*61046927SAndroid Build Coastguard Worker          disasm_a3xx_stat(ptr, blk->size / 4, state->lvl, stdout, gpu_id,
345*61046927SAndroid Build Coastguard Worker                           &stats);
346*61046927SAndroid Build Coastguard Worker          if (shaderdb) {
347*61046927SAndroid Build Coastguard Worker             unsigned dwords = 2 * stats.instlen;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker             if (gpu_id >= 400) {
350*61046927SAndroid Build Coastguard Worker                dwords = ALIGN(dwords, 16 * 2);
351*61046927SAndroid Build Coastguard Worker             } else {
352*61046927SAndroid Build Coastguard Worker                dwords = ALIGN(dwords, 4 * 2);
353*61046927SAndroid Build Coastguard Worker             }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker             unsigned half_regs = state->half_regs;
356*61046927SAndroid Build Coastguard Worker             unsigned full_regs = state->full_regs;
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker             /* On a6xx w/ merged/conflicting half and full regs, the
359*61046927SAndroid Build Coastguard Worker              * full_regs footprint will be max of full_regs and half
360*61046927SAndroid Build Coastguard Worker              * of half_regs.. we only care about which value is higher.
361*61046927SAndroid Build Coastguard Worker              */
362*61046927SAndroid Build Coastguard Worker             if (gpu_id >= 600) {
363*61046927SAndroid Build Coastguard Worker                /* footprint of half_regs in units of full_regs: */
364*61046927SAndroid Build Coastguard Worker                unsigned half_full = (half_regs + 1) / 2;
365*61046927SAndroid Build Coastguard Worker                if (half_full > full_regs)
366*61046927SAndroid Build Coastguard Worker                   full_regs = half_full;
367*61046927SAndroid Build Coastguard Worker                half_regs = 0;
368*61046927SAndroid Build Coastguard Worker             }
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker             fprintf(stderr,
371*61046927SAndroid Build Coastguard Worker                     "%s shader: %u inst, %u nops, %u non-nops, %u dwords, "
372*61046927SAndroid Build Coastguard Worker                     "%u half, %u full, %u constlen, "
373*61046927SAndroid Build Coastguard Worker                     "%u (ss), %u (sy), %d max_sun, %d loops\n",
374*61046927SAndroid Build Coastguard Worker                     state->shader_type, stats.instructions, stats.nops,
375*61046927SAndroid Build Coastguard Worker                     stats.instructions - stats.nops, dwords, half_regs,
376*61046927SAndroid Build Coastguard Worker                     full_regs, stats.constlen, stats.ss, stats.sy, 0,
377*61046927SAndroid Build Coastguard Worker                     0); /* max_sun or loops not possible */
378*61046927SAndroid Build Coastguard Worker          }
379*61046927SAndroid Build Coastguard Worker          /* this is a special case in a way, blk->count is # of
380*61046927SAndroid Build Coastguard Worker           * instructions but disasm_a3xx() decodes all instructions,
381*61046927SAndroid Build Coastguard Worker           * so just bail.
382*61046927SAndroid Build Coastguard Worker           */
383*61046927SAndroid Build Coastguard Worker          i = blk->count;
384*61046927SAndroid Build Coastguard Worker          break;
385*61046927SAndroid Build Coastguard Worker       }
386*61046927SAndroid Build Coastguard Worker       default:
387*61046927SAndroid Build Coastguard Worker          dump_unknown(state, ptr, 0, state->desc_size / 4);
388*61046927SAndroid Build Coastguard Worker          break;
389*61046927SAndroid Build Coastguard Worker       }
390*61046927SAndroid Build Coastguard Worker       ptr += state->desc_size;
391*61046927SAndroid Build Coastguard Worker    }
392*61046927SAndroid Build Coastguard Worker    state->lvl--;
393*61046927SAndroid Build Coastguard Worker }
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker /* there looks like one of these per shader, followed by "main" and
396*61046927SAndroid Build Coastguard Worker  * some more info, and then the shader itself.
397*61046927SAndroid Build Coastguard Worker  */
398*61046927SAndroid Build Coastguard Worker struct PACKED shader_info {
399*61046927SAndroid Build Coastguard Worker    uint32_t unk_0000_0010[5];
400*61046927SAndroid Build Coastguard Worker    uint32_t desc_off; /* offset to first descriptor block */
401*61046927SAndroid Build Coastguard Worker    uint32_t num_blocks;
402*61046927SAndroid Build Coastguard Worker };
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker static void
decode_shader_info(struct state * state,struct shader_info * info)405*61046927SAndroid Build Coastguard Worker decode_shader_info(struct state *state, struct shader_info *info)
406*61046927SAndroid Build Coastguard Worker {
407*61046927SAndroid Build Coastguard Worker    assert((info->desc_off % 4) == 0);
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    U(info, 0000, 0010);
410*61046927SAndroid Build Coastguard Worker    X(info, desc_off);
411*61046927SAndroid Build Coastguard Worker    D(info, num_blocks);
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    dump_unknown(state, &info[1], 0, (info->desc_off - sizeof(*info)) / 4);
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker    state->shader = info;
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker    struct shader_descriptor_block *blocks = ((void *)info) + info->desc_off;
418*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < info->num_blocks; i++) {
419*61046927SAndroid Build Coastguard Worker       printf("%sdescriptor %u:\n", tab(state->lvl), i);
420*61046927SAndroid Build Coastguard Worker       state->lvl++;
421*61046927SAndroid Build Coastguard Worker       decode_shader_descriptor_block(state, &blocks[i]);
422*61046927SAndroid Build Coastguard Worker       state->lvl--;
423*61046927SAndroid Build Coastguard Worker    }
424*61046927SAndroid Build Coastguard Worker }
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker static void
dump_program(struct state * state)427*61046927SAndroid Build Coastguard Worker dump_program(struct state *state)
428*61046927SAndroid Build Coastguard Worker {
429*61046927SAndroid Build Coastguard Worker    struct header *hdr = (void *)state->buf;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    if (dump_full)
432*61046927SAndroid Build Coastguard Worker       dump_unknown(state, state->buf, 0, state->sz / 4);
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker    decode_header(state, hdr);
435*61046927SAndroid Build Coastguard Worker }
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker int
main(int argc,char ** argv)438*61046927SAndroid Build Coastguard Worker main(int argc, char **argv)
439*61046927SAndroid Build Coastguard Worker {
440*61046927SAndroid Build Coastguard Worker    enum rd_sect_type type = RD_NONE;
441*61046927SAndroid Build Coastguard Worker    enum debug_t debug = PRINT_RAW | PRINT_STATS;
442*61046927SAndroid Build Coastguard Worker    void *buf = NULL;
443*61046927SAndroid Build Coastguard Worker    int sz;
444*61046927SAndroid Build Coastguard Worker    struct io *io;
445*61046927SAndroid Build Coastguard Worker    int raw_program = 0;
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    /* lame argument parsing: */
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker    while (1) {
450*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--verbose")) {
451*61046927SAndroid Build Coastguard Worker          debug |= PRINT_RAW | PRINT_VERBOSE;
452*61046927SAndroid Build Coastguard Worker          argv++;
453*61046927SAndroid Build Coastguard Worker          argc--;
454*61046927SAndroid Build Coastguard Worker          continue;
455*61046927SAndroid Build Coastguard Worker       }
456*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--expand")) {
457*61046927SAndroid Build Coastguard Worker          debug |= EXPAND_REPEAT;
458*61046927SAndroid Build Coastguard Worker          argv++;
459*61046927SAndroid Build Coastguard Worker          argc--;
460*61046927SAndroid Build Coastguard Worker          continue;
461*61046927SAndroid Build Coastguard Worker       }
462*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--full")) {
463*61046927SAndroid Build Coastguard Worker          /* only short dump, original shader, symbol table, and disassembly */
464*61046927SAndroid Build Coastguard Worker          dump_full = 1;
465*61046927SAndroid Build Coastguard Worker          argv++;
466*61046927SAndroid Build Coastguard Worker          argc--;
467*61046927SAndroid Build Coastguard Worker          continue;
468*61046927SAndroid Build Coastguard Worker       }
469*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--dump-offsets")) {
470*61046927SAndroid Build Coastguard Worker          dump_offsets = 1;
471*61046927SAndroid Build Coastguard Worker          argv++;
472*61046927SAndroid Build Coastguard Worker          argc--;
473*61046927SAndroid Build Coastguard Worker          continue;
474*61046927SAndroid Build Coastguard Worker       }
475*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--raw")) {
476*61046927SAndroid Build Coastguard Worker          raw_program = 1;
477*61046927SAndroid Build Coastguard Worker          argv++;
478*61046927SAndroid Build Coastguard Worker          argc--;
479*61046927SAndroid Build Coastguard Worker          continue;
480*61046927SAndroid Build Coastguard Worker       }
481*61046927SAndroid Build Coastguard Worker       if ((argc > 1) && !strcmp(argv[1], "--shaderdb")) {
482*61046927SAndroid Build Coastguard Worker          shaderdb = 1;
483*61046927SAndroid Build Coastguard Worker          argv++;
484*61046927SAndroid Build Coastguard Worker          argc--;
485*61046927SAndroid Build Coastguard Worker          continue;
486*61046927SAndroid Build Coastguard Worker       }
487*61046927SAndroid Build Coastguard Worker       break;
488*61046927SAndroid Build Coastguard Worker    }
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker    if (argc != 2) {
491*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "usage: pgmdump2 [--verbose] [--expand] [--full] "
492*61046927SAndroid Build Coastguard Worker                       "[--dump-offsets] [--raw] [--shaderdb] testlog.rd\n");
493*61046927SAndroid Build Coastguard Worker       return -1;
494*61046927SAndroid Build Coastguard Worker    }
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    disasm_a3xx_set_debug(debug);
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker    infile = argv[1];
499*61046927SAndroid Build Coastguard Worker 
500*61046927SAndroid Build Coastguard Worker    io = io_open(infile);
501*61046927SAndroid Build Coastguard Worker    if (!io) {
502*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "could not open: %s\n", infile);
503*61046927SAndroid Build Coastguard Worker       return -1;
504*61046927SAndroid Build Coastguard Worker    }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    if (raw_program) {
507*61046927SAndroid Build Coastguard Worker       io_readn(io, &sz, 4);
508*61046927SAndroid Build Coastguard Worker       free(buf);
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker       /* note: allow hex dumps to go a bit past the end of the buffer..
511*61046927SAndroid Build Coastguard Worker        * might see some garbage, but better than missing the last few bytes..
512*61046927SAndroid Build Coastguard Worker        */
513*61046927SAndroid Build Coastguard Worker       buf = calloc(1, sz + 3);
514*61046927SAndroid Build Coastguard Worker       io_readn(io, buf + 4, sz);
515*61046927SAndroid Build Coastguard Worker       (*(int *)buf) = sz;
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker       struct state state = {
518*61046927SAndroid Build Coastguard Worker          .buf = buf,
519*61046927SAndroid Build Coastguard Worker          .sz = sz,
520*61046927SAndroid Build Coastguard Worker       };
521*61046927SAndroid Build Coastguard Worker       printf("############################################################\n");
522*61046927SAndroid Build Coastguard Worker       printf("program:\n");
523*61046927SAndroid Build Coastguard Worker       dump_program(&state);
524*61046927SAndroid Build Coastguard Worker       printf("############################################################\n");
525*61046927SAndroid Build Coastguard Worker       return 0;
526*61046927SAndroid Build Coastguard Worker    }
527*61046927SAndroid Build Coastguard Worker 
528*61046927SAndroid Build Coastguard Worker    /* figure out what sort of input we are dealing with: */
529*61046927SAndroid Build Coastguard Worker    if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) {
530*61046927SAndroid Build Coastguard Worker       int ret;
531*61046927SAndroid Build Coastguard Worker       buf = calloc(1, 100 * 1024);
532*61046927SAndroid Build Coastguard Worker       ret = io_readn(io, buf, 100 * 1024);
533*61046927SAndroid Build Coastguard Worker       if (ret < 0) {
534*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "error: %m");
535*61046927SAndroid Build Coastguard Worker          return -1;
536*61046927SAndroid Build Coastguard Worker       }
537*61046927SAndroid Build Coastguard Worker       return disasm_a3xx(buf, ret / 4, 0, stdout, gpu_id);
538*61046927SAndroid Build Coastguard Worker    }
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker    while ((io_readn(io, &type, sizeof(type)) > 0) &&
541*61046927SAndroid Build Coastguard Worker           (io_readn(io, &sz, 4) > 0)) {
542*61046927SAndroid Build Coastguard Worker       free(buf);
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker       /* note: allow hex dumps to go a bit past the end of the buffer..
545*61046927SAndroid Build Coastguard Worker        * might see some garbage, but better than missing the last few bytes..
546*61046927SAndroid Build Coastguard Worker        */
547*61046927SAndroid Build Coastguard Worker       buf = calloc(1, sz + 3);
548*61046927SAndroid Build Coastguard Worker       io_readn(io, buf, sz);
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker       switch (type) {
551*61046927SAndroid Build Coastguard Worker       case RD_TEST:
552*61046927SAndroid Build Coastguard Worker          if (dump_full)
553*61046927SAndroid Build Coastguard Worker             printf("test: %s\n", (char *)buf);
554*61046927SAndroid Build Coastguard Worker          break;
555*61046927SAndroid Build Coastguard Worker       case RD_VERT_SHADER:
556*61046927SAndroid Build Coastguard Worker          printf("vertex shader:\n%s\n", (char *)buf);
557*61046927SAndroid Build Coastguard Worker          break;
558*61046927SAndroid Build Coastguard Worker       case RD_FRAG_SHADER:
559*61046927SAndroid Build Coastguard Worker          printf("fragment shader:\n%s\n", (char *)buf);
560*61046927SAndroid Build Coastguard Worker          break;
561*61046927SAndroid Build Coastguard Worker       case RD_PROGRAM: {
562*61046927SAndroid Build Coastguard Worker          struct state state = {
563*61046927SAndroid Build Coastguard Worker             .buf = buf,
564*61046927SAndroid Build Coastguard Worker             .sz = sz,
565*61046927SAndroid Build Coastguard Worker          };
566*61046927SAndroid Build Coastguard Worker          printf(
567*61046927SAndroid Build Coastguard Worker             "############################################################\n");
568*61046927SAndroid Build Coastguard Worker          printf("program:\n");
569*61046927SAndroid Build Coastguard Worker          dump_program(&state);
570*61046927SAndroid Build Coastguard Worker          printf(
571*61046927SAndroid Build Coastguard Worker             "############################################################\n");
572*61046927SAndroid Build Coastguard Worker          break;
573*61046927SAndroid Build Coastguard Worker       }
574*61046927SAndroid Build Coastguard Worker       case RD_GPU_ID:
575*61046927SAndroid Build Coastguard Worker          gpu_id = *((unsigned int *)buf);
576*61046927SAndroid Build Coastguard Worker          printf("gpu_id: %d\n", gpu_id);
577*61046927SAndroid Build Coastguard Worker          break;
578*61046927SAndroid Build Coastguard Worker       default:
579*61046927SAndroid Build Coastguard Worker          break;
580*61046927SAndroid Build Coastguard Worker       }
581*61046927SAndroid Build Coastguard Worker    }
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker    io_close(io);
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker    return 0;
586*61046927SAndroid Build Coastguard Worker }
587