2 * Copyright (c) 2019 Vasily Khoruzhick <anarsoul@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "util/ralloc.h"
32 #include "ir/pp/codegen.h"
33 #include "ir/gp/codegen.h"
38 printf("Usage: lima_disasm [OPTIONS]... FILE\n");
39 printf(" --help - show this message\n");
42 typedef struct __attribute__((__packed__
)) {
47 /* Parses an MBS1 file. MBS1 is used for Mali-400 and earlier which only support
48 * GLES2, as opposed to MBS2 which is used by later Mali gens, and contains
49 * the entire inferface between the compiler and the (blob) driver. It's
50 * produced by the offline compiler as well as glGetProgramBinary(). The
51 * format is documented at
52 * https://web.archive.org/web/20171026141029/http://limadriver.org/MBS+File+Format/
53 * and consists of a bunch of nested "chunks" where each chunk has a
54 * 4-character tag followed by a 32-bit size, then the contents of the chunk.
55 * The chunks are nested as follows:
58 * - optional CFRA (fragment shader)
59 * - core version (uint32_t, Mali-200 vs Mali-400)
60 * - FSTA (Fragment STAck information)
61 * - FDIS (if Fragment shader contains a DIScard instruction)
62 * - FBUU (information on color/depth reads/writes)
63 * - SUNI (uniform symbol table)
64 * - SVAR (varying symbol table)
65 * - DBIN (the actual code)
66 * - optional CVER (vertex shader)
67 * - core version (uint32_t, GP2 vs Mali-400)
68 * - FINS (# of instruction and attrib_prefetch)
69 * - SUNI (uniform table)
70 * - SATT (attribute table)
71 * - SVAR (varying table)
72 * - DBIN (the actual code)
74 * This routine just finds the DBIN chunk and returns the binary assuming
75 * there's only the fragment or vertex shader. We don't bother to parse the
79 extract_shader_binary(char *filename
, uint32_t *size
, bool *is_frag
)
83 if (!filename
|| !size
|| !is_frag
)
86 FILE *in
= fopen(filename
, "rb");
90 if (!fread(&chunk
, sizeof(chunk
), 1, in
)) {
91 printf("Failed to read MBS1 segment\n");
95 if (strncmp(chunk
.name
, "MBS1", 4)) {
96 printf("File is not MBS\n");
100 if (!fread(&chunk
, sizeof(chunk
), 1, in
)) {
101 printf("Failed to read shader segment\n");
105 if (!strncmp(chunk
.name
, "CFRA", 4)) {
107 } else if (!strncmp(chunk
.name
, "CVER", 4)) {
110 printf("Unsupported shader type\n");
115 fseek(in
, 4, SEEK_CUR
);
117 /* Skip the other chunks and find the DBIN chunk. */
119 if (!fread(&chunk
, sizeof(chunk
), 1, in
)) {
120 printf("Failed to read segment\n");
123 if (!strncmp(chunk
.name
, "DBIN", 4))
125 fseek(in
, chunk
.size
, SEEK_CUR
);
129 printf("CBIN segment not found!\n");
135 uint32_t *bin
= ralloc_size(NULL
, chunk
.size
);
137 printf("Failed to allocate shader binary\n");
141 if (!fread(bin
, chunk
.size
, 1, in
)) {
142 printf("Failed to read shader binary\n");
151 main(int argc
, char **argv
)
161 for (n
= 1; n
< argc
; n
++) {
162 if (!strcmp(argv
[n
], "--help")) {
170 char *filename
= NULL
;
174 uint32_t *prog
= extract_shader_binary(filename
, &size
, &is_frag
);
176 printf("Failed to parse mbs!\n");
181 assert((size
& 0x3) == 0);
183 uint32_t *bin
= prog
;
186 ppir_codegen_ctrl
*ctrl
= (ppir_codegen_ctrl
*)bin
;
187 printf("@%6d: ", offset
);
188 ppir_disassemble_instr(bin
, offset
);
190 offset
+= ctrl
->count
;
194 gpir_disassemble_program((gpir_codegen_instr
*)prog
, size
/ (sizeof(gpir_codegen_instr
)));