Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/lima/standalone/lima_disasm.c
4574 views
1
/*
2
* Copyright (c) 2019 Vasily Khoruzhick <[email protected]>
3
*
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:
10
*
11
* The above copyright notice and this permission notice (including the
12
* next paragraph) shall be included in all copies or substantial portions
13
* of the Software.
14
*
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.
22
*
23
*/
24
25
#include "util/ralloc.h"
26
27
#include <err.h>
28
#include <stdio.h>
29
#include <string.h>
30
#include <stdint.h>
31
32
#include "ir/pp/codegen.h"
33
#include "ir/gp/codegen.h"
34
35
static void
36
print_usage(void)
37
{
38
printf("Usage: lima_disasm [OPTIONS]... FILE\n");
39
printf(" --help - show this message\n");
40
}
41
42
typedef struct __attribute__((__packed__)) {
43
char name[4];
44
uint32_t size;
45
} mbs_chunk;
46
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:
56
*
57
* - MBS1
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)
73
*
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
76
* other stuff yet.
77
*/
78
static uint32_t *
79
extract_shader_binary(char *filename, uint32_t *size, bool *is_frag)
80
{
81
mbs_chunk chunk;
82
83
if (!filename || !size || !is_frag)
84
return NULL;
85
86
FILE *in = fopen(filename, "rb");
87
if (!in)
88
return NULL;
89
90
if (!fread(&chunk, sizeof(chunk), 1, in)) {
91
printf("Failed to read MBS1 segment\n");
92
return NULL;
93
}
94
95
if (strncmp(chunk.name, "MBS1", 4)) {
96
printf("File is not MBS\n");
97
return NULL;
98
}
99
100
if (!fread(&chunk, sizeof(chunk), 1, in)) {
101
printf("Failed to read shader segment\n");
102
return NULL;
103
}
104
105
if (!strncmp(chunk.name, "CFRA", 4)) {
106
*is_frag = true;
107
} else if (!strncmp(chunk.name, "CVER", 4)) {
108
*is_frag = false;
109
} else {
110
printf("Unsupported shader type\n");
111
return NULL;
112
}
113
114
/* Skip version */
115
fseek(in, 4, SEEK_CUR);
116
117
/* Skip the other chunks and find the DBIN chunk. */
118
do {
119
if (!fread(&chunk, sizeof(chunk), 1, in)) {
120
printf("Failed to read segment\n");
121
return NULL;
122
}
123
if (!strncmp(chunk.name, "DBIN", 4))
124
break;
125
fseek(in, chunk.size, SEEK_CUR);
126
} while (!feof(in));
127
128
if (feof(in)) {
129
printf("CBIN segment not found!\n");
130
return NULL;
131
}
132
133
*size = chunk.size;
134
135
uint32_t *bin = ralloc_size(NULL, chunk.size);
136
if (!bin) {
137
printf("Failed to allocate shader binary\n");
138
return NULL;
139
}
140
141
if (!fread(bin, chunk.size, 1, in)) {
142
printf("Failed to read shader binary\n");
143
ralloc_free(bin);
144
bin = NULL;
145
}
146
147
return bin;
148
}
149
150
int
151
main(int argc, char **argv)
152
{
153
int n;
154
bool is_frag = true;
155
156
if (argc < 2) {
157
print_usage();
158
return 1;
159
}
160
161
for (n = 1; n < argc; n++) {
162
if (!strcmp(argv[n], "--help")) {
163
print_usage();
164
return 1;
165
}
166
}
167
168
char *filename = NULL;
169
filename = argv[n];
170
171
uint32_t size = 0;
172
uint32_t *prog = extract_shader_binary(filename, &size, &is_frag);
173
if (!prog) {
174
printf("Failed to parse mbs!\n");
175
return -1;
176
}
177
178
if (is_frag) {
179
assert((size & 0x3) == 0);
180
size >>= 2;
181
uint32_t *bin = prog;
182
uint32_t offset = 0;
183
do {
184
ppir_codegen_ctrl *ctrl = (ppir_codegen_ctrl *)bin;
185
printf("@%6d: ", offset);
186
ppir_disassemble_instr(bin, offset);
187
bin += ctrl->count;
188
offset += ctrl->count;
189
size -= ctrl->count;
190
} while (size);
191
} else {
192
gpir_disassemble_program((gpir_codegen_instr *)prog, size / (sizeof(gpir_codegen_instr)));
193
}
194
195
ralloc_free(prog);
196
197
return 0;
198
}
199
200
201