Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/rnn/rnndec.c
4565 views
1
/*
2
* Copyright (C) 2010-2011 Marcin Koƛcielnicki <[email protected]>
3
* Copyright (C) 2010 Francisco Jerez <[email protected]>
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
12
*
13
* The above copyright notice and this permission notice (including the next
14
* paragraph) shall be included in all copies or substantial portions of the
15
* Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
* OTHER DEALINGS IN THE SOFTWARE.
24
*/
25
26
#include "rnndec.h"
27
#include <assert.h>
28
#include <stdio.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#include <inttypes.h>
32
#include "util.h"
33
#include "util/compiler.h"
34
35
struct rnndeccontext *rnndec_newcontext(struct rnndb *db) {
36
struct rnndeccontext *res = calloc (sizeof *res, 1);
37
res->db = db;
38
res->colors = &envy_null_colors;
39
return res;
40
}
41
42
int rnndec_varadd(struct rnndeccontext *ctx, char *varset, const char *variant) {
43
struct rnnenum *en = rnn_findenum(ctx->db, varset);
44
if (!en) {
45
fprintf (stderr, "Enum %s doesn't exist in database!\n", varset);
46
return 0;
47
}
48
int i, j;
49
for (i = 0; i < en->valsnum; i++)
50
if (!strcasecmp(en->vals[i]->name, variant)) {
51
struct rnndecvariant *ci = calloc (sizeof *ci, 1);
52
ci->en = en;
53
ci->variant = i;
54
ADDARRAY(ctx->vars, ci);
55
return 1;
56
}
57
58
if (i == en->valsnum) {
59
fprintf (stderr, "Variant %s doesn't exist in enum %s!\n", variant, varset);
60
return 0;
61
}
62
63
for (j = 0; j < ctx->varsnum; j++) {
64
if (ctx->vars[j]->en == en) {
65
ctx->vars[j]->variant = i;
66
break;
67
}
68
}
69
70
if (i == ctx->varsnum) {
71
struct rnndecvariant *ci = calloc (sizeof *ci, 1);
72
ci->en = en;
73
ci->variant = i;
74
ADDARRAY(ctx->vars, ci);
75
}
76
77
return 1;
78
}
79
80
int rnndec_varmatch(struct rnndeccontext *ctx, struct rnnvarinfo *vi) {
81
if (vi->dead)
82
return 0;
83
int i;
84
for (i = 0; i < vi->varsetsnum; i++) {
85
int j;
86
for (j = 0; j < ctx->varsnum; j++)
87
if (vi->varsets[i]->venum == ctx->vars[j]->en)
88
break;
89
if (j == ctx->varsnum) {
90
fprintf (stderr, "I don't know which %s variant to use!\n", vi->varsets[i]->venum->name);
91
} else {
92
if (!vi->varsets[i]->variants[ctx->vars[j]->variant])
93
return 0;
94
}
95
}
96
return 1;
97
}
98
99
/* see https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
100
static uint32_t float16i(uint16_t val)
101
{
102
uint32_t sign = ((uint32_t)(val & 0x8000)) << 16;
103
uint32_t frac = val & 0x3ff;
104
int32_t expn = (val >> 10) & 0x1f;
105
106
if (expn == 0) {
107
if (frac) {
108
/* denormalized number: */
109
int shift = __builtin_clz(frac) - 21;
110
frac <<= shift;
111
expn = -shift;
112
} else {
113
/* +/- zero: */
114
return sign;
115
}
116
} else if (expn == 0x1f) {
117
/* Inf/NaN: */
118
return sign | 0x7f800000 | (frac << 13);
119
}
120
121
return sign | ((expn + 127 - 15) << 23) | (frac << 13);
122
}
123
static float float16(uint16_t val)
124
{
125
union { uint32_t i; float f; } u;
126
u.i = float16i(val);
127
return u.f;
128
}
129
130
static const char *rnndec_decode_enum_val(struct rnndeccontext *ctx,
131
struct rnnvalue **vals, int valsnum, uint64_t value)
132
{
133
int i;
134
for (i = 0; i < valsnum; i++)
135
if (rnndec_varmatch(ctx, &vals[i]->varinfo) &&
136
vals[i]->valvalid && vals[i]->value == value)
137
return vals[i]->name;
138
return NULL;
139
}
140
141
const char *rnndec_decode_enum(struct rnndeccontext *ctx, const char *enumname, uint64_t enumval)
142
{
143
struct rnnenum *en = rnn_findenum (ctx->db, enumname);
144
if (en) {
145
return rnndec_decode_enum_val(ctx, en->vals, en->valsnum, enumval);
146
}
147
return NULL;
148
}
149
150
/* The name UNK%u is used as a placeholder for bitfields that exist but
151
* have an unknown function.
152
*/
153
static int is_unknown(const char *name)
154
{
155
unsigned u;
156
return sscanf(name, "UNK%u", &u) == 1;
157
}
158
159
char *rnndec_decodeval(struct rnndeccontext *ctx, struct rnntypeinfo *ti, uint64_t value) {
160
int width = ti->high - ti->low + 1;
161
char *res = 0;
162
int i;
163
struct rnnvalue **vals;
164
int valsnum;
165
struct rnnbitfield **bitfields;
166
int bitfieldsnum;
167
char *tmp;
168
const char *ctmp;
169
uint64_t mask, value_orig;
170
if (!ti)
171
goto failhex;
172
value_orig = value;
173
value = (value & typeinfo_mask(ti)) >> ti->low;
174
value <<= ti->shr;
175
176
switch (ti->type) {
177
case RNN_TTYPE_ENUM:
178
vals = ti->eenum->vals;
179
valsnum = ti->eenum->valsnum;
180
goto doenum;
181
case RNN_TTYPE_INLINE_ENUM:
182
vals = ti->vals;
183
valsnum = ti->valsnum;
184
goto doenum;
185
doenum:
186
ctmp = rnndec_decode_enum_val(ctx, vals, valsnum, value);
187
if (ctmp) {
188
asprintf (&res, "%s%s%s", ctx->colors->eval, ctmp, ctx->colors->reset);
189
if (ti->addvariant) {
190
rnndec_varadd(ctx, ti->eenum->name, ctmp);
191
}
192
break;
193
}
194
goto failhex;
195
case RNN_TTYPE_BITSET:
196
bitfields = ti->ebitset->bitfields;
197
bitfieldsnum = ti->ebitset->bitfieldsnum;
198
goto dobitset;
199
case RNN_TTYPE_INLINE_BITSET:
200
bitfields = ti->bitfields;
201
bitfieldsnum = ti->bitfieldsnum;
202
goto dobitset;
203
dobitset:
204
mask = 0;
205
for (i = 0; i < bitfieldsnum; i++) {
206
if (!rnndec_varmatch(ctx, &bitfields[i]->varinfo))
207
continue;
208
uint64_t type_mask = typeinfo_mask(&bitfields[i]->typeinfo);
209
if (((value & type_mask) == 0) && is_unknown(bitfields[i]->name))
210
continue;
211
mask |= type_mask;
212
if (bitfields[i]->typeinfo.type == RNN_TTYPE_BOOLEAN) {
213
const char *color = is_unknown(bitfields[i]->name) ?
214
ctx->colors->err : ctx->colors->mod;
215
if (value & type_mask) {
216
if (!res)
217
asprintf (&res, "%s%s%s", color, bitfields[i]->name, ctx->colors->reset);
218
else {
219
asprintf (&tmp, "%s | %s%s%s", res, color, bitfields[i]->name, ctx->colors->reset);
220
free(res);
221
res = tmp;
222
}
223
}
224
continue;
225
}
226
char *subval;
227
if (is_unknown(bitfields[i]->name) && (bitfields[i]->typeinfo.type != RNN_TTYPE_A3XX_REGID)) {
228
uint64_t field_val = value & type_mask;
229
field_val = (field_val & typeinfo_mask(&bitfields[i]->typeinfo)) >> bitfields[i]->typeinfo.low;
230
field_val <<= bitfields[i]->typeinfo.shr;
231
asprintf (&subval, "%s%#"PRIx64"%s", ctx->colors->err, field_val, ctx->colors->reset);
232
} else {
233
subval = rnndec_decodeval(ctx, &bitfields[i]->typeinfo, value & type_mask);
234
}
235
if (!res)
236
asprintf (&res, "%s%s%s = %s", ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval);
237
else {
238
asprintf (&tmp, "%s | %s%s%s = %s", res, ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval);
239
free(res);
240
res = tmp;
241
}
242
free(subval);
243
}
244
if (value & ~mask) {
245
if (!res)
246
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->err, value & ~mask, ctx->colors->reset);
247
else {
248
asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value & ~mask, ctx->colors->reset);
249
free(res);
250
res = tmp;
251
}
252
}
253
if (!res)
254
asprintf (&res, "%s0%s", ctx->colors->num, ctx->colors->reset);
255
asprintf (&tmp, "{ %s }", res);
256
free(res);
257
return tmp;
258
case RNN_TTYPE_SPECTYPE:
259
return rnndec_decodeval(ctx, &ti->spectype->typeinfo, value);
260
case RNN_TTYPE_HEX:
261
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset);
262
break;
263
case RNN_TTYPE_FIXED:
264
if (value & UINT64_C(1) << (width-1)) {
265
asprintf (&res, "%s-%lf%s", ctx->colors->num,
266
((double)((UINT64_C(1) << width) - value)) / ((double)(1 << ti->radix)),
267
ctx->colors->reset);
268
break;
269
}
270
FALLTHROUGH;
271
case RNN_TTYPE_UFIXED:
272
asprintf (&res, "%s%lf%s", ctx->colors->num,
273
((double)value) / ((double)(1LL << ti->radix)),
274
ctx->colors->reset);
275
break;
276
case RNN_TTYPE_A3XX_REGID:
277
asprintf (&res, "%sr%"PRIu64".%c%s", ctx->colors->num, (value >> 2), "xyzw"[value & 0x3], ctx->colors->reset);
278
break;
279
case RNN_TTYPE_UINT:
280
asprintf (&res, "%s%"PRIu64"%s", ctx->colors->num, value, ctx->colors->reset);
281
break;
282
case RNN_TTYPE_INT:
283
if (value & UINT64_C(1) << (width-1))
284
asprintf (&res, "%s-%"PRIi64"%s", ctx->colors->num, (UINT64_C(1) << width) - value, ctx->colors->reset);
285
else
286
asprintf (&res, "%s%"PRIi64"%s", ctx->colors->num, value, ctx->colors->reset);
287
break;
288
case RNN_TTYPE_BOOLEAN:
289
if (value == 0) {
290
asprintf (&res, "%sFALSE%s", ctx->colors->eval, ctx->colors->reset);
291
} else if (value == 1) {
292
asprintf (&res, "%sTRUE%s", ctx->colors->eval, ctx->colors->reset);
293
}
294
break;
295
case RNN_TTYPE_FLOAT: {
296
union { uint64_t i; float f; double d; } val;
297
val.i = value;
298
if (width == 64)
299
asprintf(&res, "%s%f%s", ctx->colors->num,
300
val.d, ctx->colors->reset);
301
else if (width == 32)
302
asprintf(&res, "%s%f%s", ctx->colors->num,
303
val.f, ctx->colors->reset);
304
else if (width == 16)
305
asprintf(&res, "%s%f%s", ctx->colors->num,
306
float16(value), ctx->colors->reset);
307
else
308
goto failhex;
309
310
break;
311
}
312
failhex:
313
default:
314
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset);
315
break;
316
}
317
if (value_orig & ~typeinfo_mask(ti)) {
318
asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value_orig & ~typeinfo_mask(ti), ctx->colors->reset);
319
free(res);
320
res = tmp;
321
}
322
return res;
323
}
324
325
static char *appendidx (struct rnndeccontext *ctx, char *name, uint64_t idx, struct rnnenum *index) {
326
char *res;
327
const char *index_name = NULL;
328
329
if (index)
330
index_name = rnndec_decode_enum_val(ctx, index->vals, index->valsnum, idx);
331
332
if (index_name)
333
asprintf (&res, "%s[%s%s%s]", name, ctx->colors->eval, index_name, ctx->colors->reset);
334
else
335
asprintf (&res, "%s[%s%#"PRIx64"%s]", name, ctx->colors->num, idx, ctx->colors->reset);
336
337
free (name);
338
return res;
339
}
340
341
/* This could probably be made to work for stripes too.. */
342
static int get_array_idx_offset(struct rnndelem *elem, uint64_t addr, uint64_t *idx, uint64_t *offset)
343
{
344
if (elem->offsets) {
345
int i;
346
for (i = 0; i < elem->offsetsnum; i++) {
347
uint64_t o = elem->offsets[i];
348
if ((o <= addr) && (addr < (o + elem->stride))) {
349
*idx = i;
350
*offset = addr - o;
351
return 0;
352
}
353
}
354
return -1;
355
} else {
356
if (addr < elem->offset)
357
return -1;
358
359
*idx = (addr - elem->offset) / elem->stride;
360
*offset = (addr - elem->offset) % elem->stride;
361
362
if (elem->length && (*idx >= elem->length))
363
return -1;
364
365
return 0;
366
}
367
}
368
369
static struct rnndecaddrinfo *trymatch (struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum, uint64_t addr, int write, int dwidth, uint64_t *indices, int indicesnum) {
370
struct rnndecaddrinfo *res;
371
int i, j;
372
for (i = 0; i < elemsnum; i++) {
373
if (!rnndec_varmatch(ctx, &elems[i]->varinfo))
374
continue;
375
uint64_t offset, idx;
376
char *tmp, *name;
377
switch (elems[i]->type) {
378
case RNN_ETYPE_REG:
379
if (addr < elems[i]->offset)
380
break;
381
if (elems[i]->stride) {
382
idx = (addr-elems[i]->offset)/elems[i]->stride;
383
offset = (addr-elems[i]->offset)%elems[i]->stride;
384
} else {
385
idx = 0;
386
offset = addr-elems[i]->offset;
387
}
388
if (offset >= elems[i]->width/dwidth)
389
break;
390
if (elems[i]->length && idx >= elems[i]->length)
391
break;
392
res = calloc (sizeof *res, 1);
393
res->typeinfo = &elems[i]->typeinfo;
394
res->width = elems[i]->width;
395
asprintf (&res->name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
396
for (j = 0; j < indicesnum; j++)
397
res->name = appendidx(ctx, res->name, indices[j], NULL);
398
if (elems[i]->length != 1)
399
res->name = appendidx(ctx, res->name, idx, elems[i]->index);
400
if (offset) {
401
/* use _HI suffix for addresses */
402
if (offset == 1 &&
403
(!strcmp(res->typeinfo->name, "address") ||
404
!strcmp(res->typeinfo->name, "waddress"))) {
405
asprintf (&tmp, "%s_HI", res->name);
406
} else {
407
asprintf (&tmp, "%s+%s%#"PRIx64"%s", res->name, ctx->colors->err, offset, ctx->colors->reset);
408
}
409
free(res->name);
410
res->name = tmp;
411
}
412
return res;
413
case RNN_ETYPE_STRIPE:
414
for (idx = 0; idx < elems[i]->length || !elems[i]->length; idx++) {
415
if (addr < elems[i]->offset + elems[i]->stride * idx)
416
break;
417
offset = addr - (elems[i]->offset + elems[i]->stride * idx);
418
int extraidx = (elems[i]->length != 1);
419
int nindnum = (elems[i]->name ? 0 : indicesnum + extraidx);
420
uint64_t nind[nindnum];
421
if (!elems[i]->name) {
422
for (j = 0; j < indicesnum; j++)
423
nind[j] = indices[j];
424
if (extraidx)
425
nind[indicesnum] = idx;
426
}
427
res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, nind, nindnum);
428
if (!res)
429
continue;
430
if (!elems[i]->name)
431
return res;
432
asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
433
for (j = 0; j < indicesnum; j++)
434
name = appendidx(ctx, name, indices[j], NULL);
435
if (elems[i]->length != 1)
436
name = appendidx(ctx, name, idx, elems[i]->index);
437
asprintf (&tmp, "%s.%s", name, res->name);
438
free(name);
439
free(res->name);
440
res->name = tmp;
441
return res;
442
}
443
break;
444
case RNN_ETYPE_ARRAY:
445
if (get_array_idx_offset(elems[i], addr, &idx, &offset))
446
break;
447
asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
448
for (j = 0; j < indicesnum; j++)
449
name = appendidx(ctx, name, indices[j], NULL);
450
if (elems[i]->length != 1)
451
name = appendidx(ctx, name, idx, elems[i]->index);
452
if ((res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, 0, 0))) {
453
asprintf (&tmp, "%s.%s", name, res->name);
454
free(name);
455
free(res->name);
456
res->name = tmp;
457
return res;
458
}
459
res = calloc (sizeof *res, 1);
460
asprintf (&tmp, "%s+%s%#"PRIx64"%s", name, ctx->colors->err, offset, ctx->colors->reset);
461
free(name);
462
res->name = tmp;
463
return res;
464
default:
465
break;
466
}
467
}
468
return 0;
469
}
470
471
int rnndec_checkaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) {
472
struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0);
473
if (res) {
474
free(res->name);
475
free(res);
476
}
477
return res != NULL;
478
}
479
480
struct rnndecaddrinfo *rnndec_decodeaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) {
481
struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0);
482
if (res)
483
return res;
484
res = calloc (sizeof *res, 1);
485
asprintf (&res->name, "%s%#"PRIx64"%s", ctx->colors->err, addr, ctx->colors->reset);
486
return res;
487
}
488
489
static unsigned tryreg(struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum,
490
int dwidth, const char *name, uint64_t *offset)
491
{
492
int i;
493
unsigned ret;
494
const char *suffix = strchr(name, '[');
495
unsigned n = suffix ? (suffix - name) : strlen(name);
496
const char *dotsuffix = strchr(name, '.');
497
unsigned dotn = dotsuffix ? (dotsuffix - name) : strlen(name);
498
499
const char *child = NULL;
500
unsigned idx = 0;
501
502
if (suffix) {
503
const char *tmp = strchr(suffix, ']');
504
idx = strtol(suffix+1, NULL, 0);
505
child = tmp+2;
506
}
507
508
for (i = 0; i < elemsnum; i++) {
509
struct rnndelem *elem = elems[i];
510
if (!rnndec_varmatch(ctx, &elem->varinfo))
511
continue;
512
int match = elem->name && (strlen(elem->name) == n) && !strncmp(elem->name, name, n);
513
switch (elem->type) {
514
case RNN_ETYPE_REG:
515
if (match) {
516
assert(!suffix);
517
*offset = elem->offset;
518
return 1;
519
}
520
break;
521
case RNN_ETYPE_STRIPE:
522
if (elem->name) {
523
if (!dotsuffix)
524
break;
525
if (strlen(elem->name) != dotn || strncmp(elem->name, name, dotn))
526
break;
527
}
528
ret = tryreg(ctx, elem->subelems, elem->subelemsnum, dwidth,
529
elem->name ? dotsuffix : name, offset);
530
if (ret)
531
return 1;
532
break;
533
case RNN_ETYPE_ARRAY:
534
if (match) {
535
assert(suffix);
536
ret = tryreg(ctx, elem->subelems, elem->subelemsnum, dwidth, child, offset);
537
if (ret) {
538
*offset += elem->offset + (idx * elem->stride);
539
return 1;
540
}
541
}
542
break;
543
default:
544
break;
545
}
546
}
547
return 0;
548
}
549
550
uint64_t rnndec_decodereg(struct rnndeccontext *ctx, struct rnndomain *domain, const char *name)
551
{
552
uint64_t offset;
553
if (tryreg(ctx, domain->subelems, domain->subelemsnum, domain->width, name, &offset)) {
554
return offset;
555
} else {
556
return 0;
557
}
558
}
559
560