Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/afuc/util.c
4564 views
1
/*
2
* Copyright © 2021 Google, Inc.
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, sublicense,
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 next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* 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 NONINFRINGEMENT. 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 FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
* SOFTWARE.
22
*/
23
24
#include <err.h>
25
#include <stdarg.h>
26
#include <stdio.h>
27
#include <string.h>
28
29
#include "rnn.h"
30
#include "rnndec.h"
31
32
#include "afuc.h"
33
#include "util.h"
34
35
static struct rnndeccontext *ctx;
36
static struct rnndb *db;
37
static struct rnndomain *control_regs;
38
static struct rnndomain *pipe_regs;
39
struct rnndomain *dom[2];
40
static struct rnnenum *pm4_packets;
41
42
static int
43
find_reg(struct rnndomain *dom, const char *name)
44
{
45
for (int i = 0; i < dom->subelemsnum; i++)
46
if (!strcmp(name, dom->subelems[i]->name))
47
return dom->subelems[i]->offset;
48
49
return -1;
50
}
51
52
static unsigned
53
reg(struct rnndomain *dom, const char *type, const char *name)
54
{
55
int val = find_reg(dom, name);
56
if (val < 0) {
57
char *endptr = NULL;
58
val = strtol(name, &endptr, 0);
59
if (endptr && *endptr) {
60
printf("invalid %s reg: %s\n", type, name);
61
exit(2);
62
}
63
}
64
return (unsigned)val;
65
}
66
67
static char *
68
reg_name(struct rnndomain *dom, unsigned id)
69
{
70
if (rnndec_checkaddr(ctx, dom, id, 0)) {
71
struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, dom, id, 0);
72
char *name = info->name;
73
free(info);
74
return name;
75
} else {
76
return NULL;
77
}
78
}
79
80
/**
81
* Map control reg name to offset.
82
*/
83
unsigned
84
afuc_control_reg(const char *name)
85
{
86
return reg(control_regs, "control", name);
87
}
88
89
/**
90
* Map offset to control reg name (or NULL), caller frees
91
*/
92
char *
93
afuc_control_reg_name(unsigned id)
94
{
95
return reg_name(control_regs, id);
96
}
97
98
/**
99
* Map pipe reg name to offset.
100
*/
101
unsigned
102
afuc_pipe_reg(const char *name)
103
{
104
return reg(pipe_regs, "pipe", name);
105
}
106
107
/**
108
* "void" pipe regs don't have a value written, the $addr right is
109
* enough to trigger what they do
110
*/
111
bool
112
afuc_pipe_reg_is_void(unsigned id)
113
{
114
if (rnndec_checkaddr(ctx, pipe_regs, id, 0)) {
115
struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, pipe_regs, id, 0);
116
free(info->name);
117
bool ret = !strcmp(info->typeinfo->name, "void");
118
free(info);
119
return ret;
120
} else {
121
return false;
122
}
123
}
124
125
/**
126
* Map offset to pipe reg name (or NULL), caller frees
127
*/
128
char *
129
afuc_pipe_reg_name(unsigned id)
130
{
131
return reg_name(pipe_regs, id);
132
}
133
134
/**
135
* Map GPU reg name to offset.
136
*/
137
unsigned
138
afuc_gpu_reg(const char *name)
139
{
140
int val = find_reg(dom[0], name);
141
if (val < 0)
142
val = find_reg(dom[1], name);
143
if (val < 0) {
144
char *endptr = NULL;
145
val = strtol(name, &endptr, 0);
146
if (endptr && *endptr) {
147
printf("invalid control reg: %s\n", name);
148
exit(2);
149
}
150
}
151
return (unsigned)val;
152
}
153
154
/**
155
* Map offset to gpu reg name (or NULL), caller frees
156
*/
157
char *
158
afuc_gpu_reg_name(unsigned id)
159
{
160
struct rnndomain *d = NULL;
161
162
if (rnndec_checkaddr(ctx, dom[0], id, 0)) {
163
d = dom[0];
164
} else if (rnndec_checkaddr(ctx, dom[1], id, 0)) {
165
d = dom[1];
166
}
167
168
if (d) {
169
struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, d, id, 0);
170
if (info) {
171
char *name = info->name;
172
free(info);
173
return name;
174
}
175
}
176
177
return NULL;
178
}
179
180
unsigned
181
afuc_gpr_reg(const char *name)
182
{
183
/* If it starts with '$' just swallow it: */
184
if (name[0] == '$')
185
name++;
186
187
/* handle aliases: */
188
if (!strcmp(name, "rem")) {
189
return REG_REM;
190
} else if (!strcmp(name, "memdata")) {
191
return REG_MEMDATA;
192
} else if (!strcmp(name, "addr")) {
193
return REG_ADDR;
194
} else if (!strcmp(name, "regdata")) {
195
return REG_REGDATA;
196
} else if (!strcmp(name, "usraddr")) {
197
return REG_USRADDR;
198
} else if (!strcmp(name, "data")) {
199
return REG_DATA;
200
} else {
201
char *endptr = NULL;
202
unsigned val = strtol(name, &endptr, 16);
203
if (endptr && *endptr) {
204
printf("invalid gpr reg: %s\n", name);
205
exit(2);
206
}
207
return val;
208
}
209
}
210
211
static int
212
find_enum_val(struct rnnenum *en, const char *name)
213
{
214
int i;
215
216
for (i = 0; i < en->valsnum; i++)
217
if (en->vals[i]->valvalid && !strcmp(name, en->vals[i]->name))
218
return en->vals[i]->value;
219
220
return -1;
221
}
222
223
/**
224
* Map pm4 packet name to id
225
*/
226
int
227
afuc_pm4_id(const char *name)
228
{
229
return find_enum_val(pm4_packets, name);
230
}
231
232
const char *
233
afuc_pm_id_name(unsigned id)
234
{
235
return rnndec_decode_enum(ctx, "adreno_pm4_type3_packets", id);
236
}
237
238
void
239
afuc_printc(enum afuc_color c, const char *fmt, ...)
240
{
241
va_list args;
242
if (c == AFUC_ERR) {
243
printf("%s", ctx->colors->err);
244
} else if (c == AFUC_LBL) {
245
printf("%s", ctx->colors->btarg);
246
}
247
va_start(args, fmt);
248
vprintf(fmt, args);
249
va_end(args);
250
printf("%s", ctx->colors->reset);
251
}
252
253
int afuc_util_init(int gpuver, bool colors)
254
{
255
char *name, *control_reg_name;
256
char *pipe_reg_name = NULL;
257
258
switch (gpuver) {
259
case 6:
260
name = "A6XX";
261
control_reg_name = "A6XX_CONTROL_REG";
262
pipe_reg_name = "A6XX_PIPE_REG";
263
break;
264
case 5:
265
name = "A5XX";
266
control_reg_name = "A5XX_CONTROL_REG";
267
pipe_reg_name = "A5XX_PIPE_REG";
268
break;
269
default:
270
fprintf(stderr, "unknown GPU version!\n");
271
return -1;
272
}
273
274
rnn_init();
275
db = rnn_newdb();
276
277
ctx = rnndec_newcontext(db);
278
ctx->colors = colors ? &envy_def_colors : &envy_null_colors;
279
280
rnn_parsefile(db, "adreno.xml");
281
rnn_prepdb(db);
282
if (db->estatus)
283
errx(db->estatus, "failed to parse register database");
284
dom[0] = rnn_finddomain(db, name);
285
dom[1] = rnn_finddomain(db, "AXXX");
286
control_regs = rnn_finddomain(db, control_reg_name);
287
pipe_regs = rnn_finddomain(db, pipe_reg_name);
288
289
rnndec_varadd(ctx, "chip", name);
290
291
pm4_packets = rnn_findenum(ctx->db, "adreno_pm4_type3_packets");
292
293
return 0;
294
}
295
296
297