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