2 * Copyright (C) 2010-2011 Marcin KoĆcielnicki <koriakin@0x04.net>
3 * Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net>
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:
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
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.
34 struct rnndeccontext
*rnndec_newcontext(struct rnndb
*db
) {
35 struct rnndeccontext
*res
= calloc (sizeof *res
, 1);
37 res
->colors
= &envy_null_colors
;
41 int rnndec_varadd(struct rnndeccontext
*ctx
, char *varset
, const char *variant
) {
42 struct rnnenum
*en
= rnn_findenum(ctx
->db
, varset
);
44 fprintf (stderr
, "Enum %s doesn't exist in database!\n", varset
);
48 for (i
= 0; i
< en
->valsnum
; i
++)
49 if (!strcasecmp(en
->vals
[i
]->name
, variant
)) {
50 struct rnndecvariant
*ci
= calloc (sizeof *ci
, 1);
53 ADDARRAY(ctx
->vars
, ci
);
57 if (i
== en
->valsnum
) {
58 fprintf (stderr
, "Variant %s doesn't exist in enum %s!\n", variant
, varset
);
62 for (j
= 0; j
< ctx
->varsnum
; j
++) {
63 if (ctx
->vars
[j
]->en
== en
) {
64 ctx
->vars
[j
]->variant
= i
;
69 if (i
== ctx
->varsnum
) {
70 struct rnndecvariant
*ci
= calloc (sizeof *ci
, 1);
73 ADDARRAY(ctx
->vars
, ci
);
79 int rnndec_varmatch(struct rnndeccontext
*ctx
, struct rnnvarinfo
*vi
) {
83 for (i
= 0; i
< vi
->varsetsnum
; i
++) {
85 for (j
= 0; j
< ctx
->varsnum
; j
++)
86 if (vi
->varsets
[i
]->venum
== ctx
->vars
[j
]->en
)
88 if (j
== ctx
->varsnum
) {
89 fprintf (stderr
, "I don't know which %s variant to use!\n", vi
->varsets
[i
]->venum
->name
);
91 if (!vi
->varsets
[i
]->variants
[ctx
->vars
[j
]->variant
])
98 /* see https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
99 static uint32_t float16i(uint16_t val
)
101 uint32_t sign
= ((uint32_t)(val
& 0x8000)) << 16;
102 uint32_t frac
= val
& 0x3ff;
103 int32_t expn
= (val
>> 10) & 0x1f;
107 /* denormalized number: */
108 int shift
= __builtin_clz(frac
) - 21;
115 } else if (expn
== 0x1f) {
117 return sign
| 0x7f800000 | (frac
<< 13);
120 return sign
| ((expn
+ 127 - 15) << 23) | (frac
<< 13);
122 static float float16(uint16_t val
)
124 union { uint32_t i
; float f
; } u
;
129 static const char *rnndec_decode_enum_val(struct rnndeccontext
*ctx
,
130 struct rnnvalue
**vals
, int valsnum
, uint64_t value
)
133 for (i
= 0; i
< valsnum
; i
++)
134 if (rnndec_varmatch(ctx
, &vals
[i
]->varinfo
) &&
135 vals
[i
]->valvalid
&& vals
[i
]->value
== value
)
136 return vals
[i
]->name
;
140 const char *rnndec_decode_enum(struct rnndeccontext
*ctx
, const char *enumname
, uint64_t enumval
)
142 struct rnnenum
*en
= rnn_findenum (ctx
->db
, enumname
);
144 return rnndec_decode_enum_val(ctx
, en
->vals
, en
->valsnum
, enumval
);
149 /* The name UNK%u is used as a placeholder for bitfields that exist but
150 * have an unknown function.
152 static int is_unknown(const char *name
)
155 return sscanf(name
, "UNK%u", &u
) == 1;
158 char *rnndec_decodeval(struct rnndeccontext
*ctx
, struct rnntypeinfo
*ti
, uint64_t value
) {
159 int width
= ti
->high
- ti
->low
+ 1;
162 struct rnnvalue
**vals
;
164 struct rnnbitfield
**bitfields
;
168 uint64_t mask
, value_orig
;
172 value
= (value
& typeinfo_mask(ti
)) >> ti
->low
;
177 vals
= ti
->eenum
->vals
;
178 valsnum
= ti
->eenum
->valsnum
;
180 case RNN_TTYPE_INLINE_ENUM
:
182 valsnum
= ti
->valsnum
;
185 ctmp
= rnndec_decode_enum_val(ctx
, vals
, valsnum
, value
);
187 asprintf (&res
, "%s%s%s", ctx
->colors
->eval
, ctmp
, ctx
->colors
->reset
);
188 if (ti
->addvariant
) {
189 rnndec_varadd(ctx
, ti
->eenum
->name
, ctmp
);
194 case RNN_TTYPE_BITSET
:
195 bitfields
= ti
->ebitset
->bitfields
;
196 bitfieldsnum
= ti
->ebitset
->bitfieldsnum
;
198 case RNN_TTYPE_INLINE_BITSET
:
199 bitfields
= ti
->bitfields
;
200 bitfieldsnum
= ti
->bitfieldsnum
;
204 for (i
= 0; i
< bitfieldsnum
; i
++) {
205 if (!rnndec_varmatch(ctx
, &bitfields
[i
]->varinfo
))
207 uint64_t type_mask
= typeinfo_mask(&bitfields
[i
]->typeinfo
);
208 if (((value
& type_mask
) == 0) && is_unknown(bitfields
[i
]->name
))
211 if (bitfields
[i
]->typeinfo
.type
== RNN_TTYPE_BOOLEAN
) {
212 const char *color
= is_unknown(bitfields
[i
]->name
) ?
213 ctx
->colors
->err
: ctx
->colors
->mod
;
214 if (value
& type_mask
) {
216 asprintf (&res
, "%s%s%s", color
, bitfields
[i
]->name
, ctx
->colors
->reset
);
218 asprintf (&tmp
, "%s | %s%s%s", res
, color
, bitfields
[i
]->name
, ctx
->colors
->reset
);
226 if (is_unknown(bitfields
[i
]->name
) && (bitfields
[i
]->typeinfo
.type
!= RNN_TTYPE_A3XX_REGID
)) {
227 uint64_t field_val
= value
& type_mask
;
228 field_val
= (field_val
& typeinfo_mask(&bitfields
[i
]->typeinfo
)) >> bitfields
[i
]->typeinfo
.low
;
229 field_val
<<= bitfields
[i
]->typeinfo
.shr
;
230 asprintf (&subval
, "%s%#"PRIx64
"%s", ctx
->colors
->err
, field_val
, ctx
->colors
->reset
);
232 subval
= rnndec_decodeval(ctx
, &bitfields
[i
]->typeinfo
, value
& type_mask
);
235 asprintf (&res
, "%s%s%s = %s", ctx
->colors
->rname
, bitfields
[i
]->name
, ctx
->colors
->reset
, subval
);
237 asprintf (&tmp
, "%s | %s%s%s = %s", res
, ctx
->colors
->rname
, bitfields
[i
]->name
, ctx
->colors
->reset
, subval
);
245 asprintf (&res
, "%s%#"PRIx64
"%s", ctx
->colors
->err
, value
& ~mask
, ctx
->colors
->reset
);
247 asprintf (&tmp
, "%s | %s%#"PRIx64
"%s", res
, ctx
->colors
->err
, value
& ~mask
, ctx
->colors
->reset
);
253 asprintf (&res
, "%s0%s", ctx
->colors
->num
, ctx
->colors
->reset
);
254 asprintf (&tmp
, "{ %s }", res
);
257 case RNN_TTYPE_SPECTYPE
:
258 return rnndec_decodeval(ctx
, &ti
->spectype
->typeinfo
, value
);
260 asprintf (&res
, "%s%#"PRIx64
"%s", ctx
->colors
->num
, value
, ctx
->colors
->reset
);
262 case RNN_TTYPE_FIXED
:
263 if (value
& UINT64_C(1) << (width
-1)) {
264 asprintf (&res
, "%s-%lf%s", ctx
->colors
->num
,
265 ((double)((UINT64_C(1) << width
) - value
)) / ((double)(1 << ti
->radix
)),
270 case RNN_TTYPE_UFIXED
:
271 asprintf (&res
, "%s%lf%s", ctx
->colors
->num
,
272 ((double)value
) / ((double)(1LL << ti
->radix
)),
275 case RNN_TTYPE_A3XX_REGID
:
276 asprintf (&res
, "%sr%"PRIu64
".%c%s", ctx
->colors
->num
, (value
>> 2), "xyzw"[value
& 0x3], ctx
->colors
->reset
);
279 asprintf (&res
, "%s%"PRIu64
"%s", ctx
->colors
->num
, value
, ctx
->colors
->reset
);
282 if (value
& UINT64_C(1) << (width
-1))
283 asprintf (&res
, "%s-%"PRIi64
"%s", ctx
->colors
->num
, (UINT64_C(1) << width
) - value
, ctx
->colors
->reset
);
285 asprintf (&res
, "%s%"PRIi64
"%s", ctx
->colors
->num
, value
, ctx
->colors
->reset
);
287 case RNN_TTYPE_BOOLEAN
:
289 asprintf (&res
, "%sFALSE%s", ctx
->colors
->eval
, ctx
->colors
->reset
);
290 } else if (value
== 1) {
291 asprintf (&res
, "%sTRUE%s", ctx
->colors
->eval
, ctx
->colors
->reset
);
294 case RNN_TTYPE_FLOAT
: {
295 union { uint64_t i
; float f
; double d
; } val
;
298 asprintf(&res
, "%s%f%s", ctx
->colors
->num
,
299 val
.d
, ctx
->colors
->reset
);
300 else if (width
== 32)
301 asprintf(&res
, "%s%f%s", ctx
->colors
->num
,
302 val
.f
, ctx
->colors
->reset
);
303 else if (width
== 16)
304 asprintf(&res
, "%s%f%s", ctx
->colors
->num
,
305 float16(value
), ctx
->colors
->reset
);
313 asprintf (&res
, "%s%#"PRIx64
"%s", ctx
->colors
->num
, value
, ctx
->colors
->reset
);
316 if (value_orig
& ~typeinfo_mask(ti
)) {
317 asprintf (&tmp
, "%s | %s%#"PRIx64
"%s", res
, ctx
->colors
->err
, value_orig
& ~typeinfo_mask(ti
), ctx
->colors
->reset
);
324 static char *appendidx (struct rnndeccontext
*ctx
, char *name
, uint64_t idx
, struct rnnenum
*index
) {
326 const char *index_name
= NULL
;
329 index_name
= rnndec_decode_enum_val(ctx
, index
->vals
, index
->valsnum
, idx
);
332 asprintf (&res
, "%s[%s%s%s]", name
, ctx
->colors
->eval
, index_name
, ctx
->colors
->reset
);
334 asprintf (&res
, "%s[%s%#"PRIx64
"%s]", name
, ctx
->colors
->num
, idx
, ctx
->colors
->reset
);
340 /* This could probably be made to work for stripes too.. */
341 static int get_array_idx_offset(struct rnndelem
*elem
, uint64_t addr
, uint64_t *idx
, uint64_t *offset
)
345 for (i
= 0; i
< elem
->offsetsnum
; i
++) {
346 uint64_t o
= elem
->offsets
[i
];
347 if ((o
<= addr
) && (addr
< (o
+ elem
->stride
))) {
355 if (addr
< elem
->offset
)
358 *idx
= (addr
- elem
->offset
) / elem
->stride
;
359 *offset
= (addr
- elem
->offset
) % elem
->stride
;
361 if (elem
->length
&& (*idx
>= elem
->length
))
368 static struct rnndecaddrinfo
*trymatch (struct rnndeccontext
*ctx
, struct rnndelem
**elems
, int elemsnum
, uint64_t addr
, int write
, int dwidth
, uint64_t *indices
, int indicesnum
) {
369 struct rnndecaddrinfo
*res
;
371 for (i
= 0; i
< elemsnum
; i
++) {
372 if (!rnndec_varmatch(ctx
, &elems
[i
]->varinfo
))
374 uint64_t offset
, idx
;
376 switch (elems
[i
]->type
) {
378 if (addr
< elems
[i
]->offset
)
380 if (elems
[i
]->stride
) {
381 idx
= (addr
-elems
[i
]->offset
)/elems
[i
]->stride
;
382 offset
= (addr
-elems
[i
]->offset
)%elems
[i
]->stride
;
385 offset
= addr
-elems
[i
]->offset
;
387 if (offset
>= elems
[i
]->width
/dwidth
)
389 if (elems
[i
]->length
&& idx
>= elems
[i
]->length
)
391 res
= calloc (sizeof *res
, 1);
392 res
->typeinfo
= &elems
[i
]->typeinfo
;
393 res
->width
= elems
[i
]->width
;
394 asprintf (&res
->name
, "%s%s%s", ctx
->colors
->rname
, elems
[i
]->name
, ctx
->colors
->reset
);
395 for (j
= 0; j
< indicesnum
; j
++)
396 res
->name
= appendidx(ctx
, res
->name
, indices
[j
], NULL
);
397 if (elems
[i
]->length
!= 1)
398 res
->name
= appendidx(ctx
, res
->name
, idx
, elems
[i
]->index
);
400 asprintf (&tmp
, "%s+%s%#"PRIx64
"%s", res
->name
, ctx
->colors
->err
, offset
, ctx
->colors
->reset
);
405 case RNN_ETYPE_STRIPE
:
406 for (idx
= 0; idx
< elems
[i
]->length
|| !elems
[i
]->length
; idx
++) {
407 if (addr
< elems
[i
]->offset
+ elems
[i
]->stride
* idx
)
409 offset
= addr
- (elems
[i
]->offset
+ elems
[i
]->stride
* idx
);
410 int extraidx
= (elems
[i
]->length
!= 1);
411 int nindnum
= (elems
[i
]->name
? 0 : indicesnum
+ extraidx
);
412 uint64_t nind
[nindnum
];
413 if (!elems
[i
]->name
) {
414 for (j
= 0; j
< indicesnum
; j
++)
415 nind
[j
] = indices
[j
];
417 nind
[indicesnum
] = idx
;
419 res
= trymatch (ctx
, elems
[i
]->subelems
, elems
[i
]->subelemsnum
, offset
, write
, dwidth
, nind
, nindnum
);
424 asprintf (&name
, "%s%s%s", ctx
->colors
->rname
, elems
[i
]->name
, ctx
->colors
->reset
);
425 for (j
= 0; j
< indicesnum
; j
++)
426 name
= appendidx(ctx
, name
, indices
[j
], NULL
);
427 if (elems
[i
]->length
!= 1)
428 name
= appendidx(ctx
, name
, idx
, elems
[i
]->index
);
429 asprintf (&tmp
, "%s.%s", name
, res
->name
);
436 case RNN_ETYPE_ARRAY
:
437 if (get_array_idx_offset(elems
[i
], addr
, &idx
, &offset
))
439 asprintf (&name
, "%s%s%s", ctx
->colors
->rname
, elems
[i
]->name
, ctx
->colors
->reset
);
440 for (j
= 0; j
< indicesnum
; j
++)
441 name
= appendidx(ctx
, name
, indices
[j
], NULL
);
442 if (elems
[i
]->length
!= 1)
443 name
= appendidx(ctx
, name
, idx
, elems
[i
]->index
);
444 if ((res
= trymatch (ctx
, elems
[i
]->subelems
, elems
[i
]->subelemsnum
, offset
, write
, dwidth
, 0, 0))) {
445 asprintf (&tmp
, "%s.%s", name
, res
->name
);
451 res
= calloc (sizeof *res
, 1);
452 asprintf (&tmp
, "%s+%s%#"PRIx64
"%s", name
, ctx
->colors
->err
, offset
, ctx
->colors
->reset
);
463 int rnndec_checkaddr(struct rnndeccontext
*ctx
, struct rnndomain
*domain
, uint64_t addr
, int write
) {
464 struct rnndecaddrinfo
*res
= trymatch(ctx
, domain
->subelems
, domain
->subelemsnum
, addr
, write
, domain
->width
, 0, 0);
472 struct rnndecaddrinfo
*rnndec_decodeaddr(struct rnndeccontext
*ctx
, struct rnndomain
*domain
, uint64_t addr
, int write
) {
473 struct rnndecaddrinfo
*res
= trymatch(ctx
, domain
->subelems
, domain
->subelemsnum
, addr
, write
, domain
->width
, 0, 0);
476 res
= calloc (sizeof *res
, 1);
477 asprintf (&res
->name
, "%s%#"PRIx64
"%s", ctx
->colors
->err
, addr
, ctx
->colors
->reset
);
481 static unsigned tryreg(struct rnndeccontext
*ctx
, struct rnndelem
**elems
, int elemsnum
,
482 int dwidth
, const char *name
, uint64_t *offset
)
486 const char *suffix
= strchr(name
, '[');
487 unsigned n
= suffix
? (suffix
- name
) : strlen(name
);
488 const char *dotsuffix
= strchr(name
, '.');
489 unsigned dotn
= dotsuffix
? (dotsuffix
- name
) : strlen(name
);
491 const char *child
= NULL
;
495 const char *tmp
= strchr(suffix
, ']');
496 idx
= strtol(suffix
+1, NULL
, 0);
500 for (i
= 0; i
< elemsnum
; i
++) {
501 struct rnndelem
*elem
= elems
[i
];
502 if (!rnndec_varmatch(ctx
, &elem
->varinfo
))
504 int match
= elem
->name
&& (strlen(elem
->name
) == n
) && !strncmp(elem
->name
, name
, n
);
505 switch (elem
->type
) {
509 *offset
= elem
->offset
;
513 case RNN_ETYPE_STRIPE
:
517 if (strlen(elem
->name
) != dotn
|| strncmp(elem
->name
, name
, dotn
))
520 ret
= tryreg(ctx
, elem
->subelems
, elem
->subelemsnum
, dwidth
,
521 elem
->name
? dotsuffix
: name
, offset
);
525 case RNN_ETYPE_ARRAY
:
528 ret
= tryreg(ctx
, elem
->subelems
, elem
->subelemsnum
, dwidth
, child
, offset
);
530 *offset
+= elem
->offset
+ (idx
* elem
->stride
);
542 uint64_t rnndec_decodereg(struct rnndeccontext
*ctx
, struct rnndomain
*domain
, const char *name
)
545 if (tryreg(ctx
, domain
->subelems
, domain
->subelemsnum
, domain
->width
, name
, &offset
)) {