17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net> 37ec681f3Smrg * Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net> 47ec681f3Smrg * All Rights Reserved. 57ec681f3Smrg * 67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 87ec681f3Smrg * to deal in the Software without restriction, including without limitation 97ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 117ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 127ec681f3Smrg * 137ec681f3Smrg * The above copyright notice and this permission notice (including the next 147ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 157ec681f3Smrg * Software. 167ec681f3Smrg * 177ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 187ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 217ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 227ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 237ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE. 247ec681f3Smrg */ 257ec681f3Smrg 267ec681f3Smrg#include "rnndec.h" 277ec681f3Smrg#include <assert.h> 287ec681f3Smrg#include <stdio.h> 297ec681f3Smrg#include <string.h> 307ec681f3Smrg#include <stdlib.h> 317ec681f3Smrg#include <inttypes.h> 327ec681f3Smrg#include "util.h" 337ec681f3Smrg#include "util/compiler.h" 347ec681f3Smrg 357ec681f3Smrgstruct rnndeccontext *rnndec_newcontext(struct rnndb *db) { 367ec681f3Smrg struct rnndeccontext *res = calloc (sizeof *res, 1); 377ec681f3Smrg res->db = db; 387ec681f3Smrg res->colors = &envy_null_colors; 397ec681f3Smrg return res; 407ec681f3Smrg} 417ec681f3Smrg 427ec681f3Smrgint rnndec_varadd(struct rnndeccontext *ctx, char *varset, const char *variant) { 437ec681f3Smrg struct rnnenum *en = rnn_findenum(ctx->db, varset); 447ec681f3Smrg if (!en) { 457ec681f3Smrg fprintf (stderr, "Enum %s doesn't exist in database!\n", varset); 467ec681f3Smrg return 0; 477ec681f3Smrg } 487ec681f3Smrg int i, j; 497ec681f3Smrg for (i = 0; i < en->valsnum; i++) 507ec681f3Smrg if (!strcasecmp(en->vals[i]->name, variant)) { 517ec681f3Smrg struct rnndecvariant *ci = calloc (sizeof *ci, 1); 527ec681f3Smrg ci->en = en; 537ec681f3Smrg ci->variant = i; 547ec681f3Smrg ADDARRAY(ctx->vars, ci); 557ec681f3Smrg return 1; 567ec681f3Smrg } 577ec681f3Smrg 587ec681f3Smrg if (i == en->valsnum) { 597ec681f3Smrg fprintf (stderr, "Variant %s doesn't exist in enum %s!\n", variant, varset); 607ec681f3Smrg return 0; 617ec681f3Smrg } 627ec681f3Smrg 637ec681f3Smrg for (j = 0; j < ctx->varsnum; j++) { 647ec681f3Smrg if (ctx->vars[j]->en == en) { 657ec681f3Smrg ctx->vars[j]->variant = i; 667ec681f3Smrg break; 677ec681f3Smrg } 687ec681f3Smrg } 697ec681f3Smrg 707ec681f3Smrg if (i == ctx->varsnum) { 717ec681f3Smrg struct rnndecvariant *ci = calloc (sizeof *ci, 1); 727ec681f3Smrg ci->en = en; 737ec681f3Smrg ci->variant = i; 747ec681f3Smrg ADDARRAY(ctx->vars, ci); 757ec681f3Smrg } 767ec681f3Smrg 777ec681f3Smrg return 1; 787ec681f3Smrg} 797ec681f3Smrg 807ec681f3Smrgint rnndec_varmatch(struct rnndeccontext *ctx, struct rnnvarinfo *vi) { 817ec681f3Smrg if (vi->dead) 827ec681f3Smrg return 0; 837ec681f3Smrg int i; 847ec681f3Smrg for (i = 0; i < vi->varsetsnum; i++) { 857ec681f3Smrg int j; 867ec681f3Smrg for (j = 0; j < ctx->varsnum; j++) 877ec681f3Smrg if (vi->varsets[i]->venum == ctx->vars[j]->en) 887ec681f3Smrg break; 897ec681f3Smrg if (j == ctx->varsnum) { 907ec681f3Smrg fprintf (stderr, "I don't know which %s variant to use!\n", vi->varsets[i]->venum->name); 917ec681f3Smrg } else { 927ec681f3Smrg if (!vi->varsets[i]->variants[ctx->vars[j]->variant]) 937ec681f3Smrg return 0; 947ec681f3Smrg } 957ec681f3Smrg } 967ec681f3Smrg return 1; 977ec681f3Smrg} 987ec681f3Smrg 997ec681f3Smrg/* see https://en.wikipedia.org/wiki/Half-precision_floating-point_format */ 1007ec681f3Smrgstatic uint32_t float16i(uint16_t val) 1017ec681f3Smrg{ 1027ec681f3Smrg uint32_t sign = ((uint32_t)(val & 0x8000)) << 16; 1037ec681f3Smrg uint32_t frac = val & 0x3ff; 1047ec681f3Smrg int32_t expn = (val >> 10) & 0x1f; 1057ec681f3Smrg 1067ec681f3Smrg if (expn == 0) { 1077ec681f3Smrg if (frac) { 1087ec681f3Smrg /* denormalized number: */ 1097ec681f3Smrg int shift = __builtin_clz(frac) - 21; 1107ec681f3Smrg frac <<= shift; 1117ec681f3Smrg expn = -shift; 1127ec681f3Smrg } else { 1137ec681f3Smrg /* +/- zero: */ 1147ec681f3Smrg return sign; 1157ec681f3Smrg } 1167ec681f3Smrg } else if (expn == 0x1f) { 1177ec681f3Smrg /* Inf/NaN: */ 1187ec681f3Smrg return sign | 0x7f800000 | (frac << 13); 1197ec681f3Smrg } 1207ec681f3Smrg 1217ec681f3Smrg return sign | ((expn + 127 - 15) << 23) | (frac << 13); 1227ec681f3Smrg} 1237ec681f3Smrgstatic float float16(uint16_t val) 1247ec681f3Smrg{ 1257ec681f3Smrg union { uint32_t i; float f; } u; 1267ec681f3Smrg u.i = float16i(val); 1277ec681f3Smrg return u.f; 1287ec681f3Smrg} 1297ec681f3Smrg 1307ec681f3Smrgstatic const char *rnndec_decode_enum_val(struct rnndeccontext *ctx, 1317ec681f3Smrg struct rnnvalue **vals, int valsnum, uint64_t value) 1327ec681f3Smrg{ 1337ec681f3Smrg int i; 1347ec681f3Smrg for (i = 0; i < valsnum; i++) 1357ec681f3Smrg if (rnndec_varmatch(ctx, &vals[i]->varinfo) && 1367ec681f3Smrg vals[i]->valvalid && vals[i]->value == value) 1377ec681f3Smrg return vals[i]->name; 1387ec681f3Smrg return NULL; 1397ec681f3Smrg} 1407ec681f3Smrg 1417ec681f3Smrgconst char *rnndec_decode_enum(struct rnndeccontext *ctx, const char *enumname, uint64_t enumval) 1427ec681f3Smrg{ 1437ec681f3Smrg struct rnnenum *en = rnn_findenum (ctx->db, enumname); 1447ec681f3Smrg if (en) { 1457ec681f3Smrg return rnndec_decode_enum_val(ctx, en->vals, en->valsnum, enumval); 1467ec681f3Smrg } 1477ec681f3Smrg return NULL; 1487ec681f3Smrg} 1497ec681f3Smrg 1507ec681f3Smrg/* The name UNK%u is used as a placeholder for bitfields that exist but 1517ec681f3Smrg * have an unknown function. 1527ec681f3Smrg */ 1537ec681f3Smrgstatic int is_unknown(const char *name) 1547ec681f3Smrg{ 1557ec681f3Smrg unsigned u; 1567ec681f3Smrg return sscanf(name, "UNK%u", &u) == 1; 1577ec681f3Smrg} 1587ec681f3Smrg 1597ec681f3Smrgchar *rnndec_decodeval(struct rnndeccontext *ctx, struct rnntypeinfo *ti, uint64_t value) { 1607ec681f3Smrg int width = ti->high - ti->low + 1; 1617ec681f3Smrg char *res = 0; 1627ec681f3Smrg int i; 1637ec681f3Smrg struct rnnvalue **vals; 1647ec681f3Smrg int valsnum; 1657ec681f3Smrg struct rnnbitfield **bitfields; 1667ec681f3Smrg int bitfieldsnum; 1677ec681f3Smrg char *tmp; 1687ec681f3Smrg const char *ctmp; 1697ec681f3Smrg uint64_t mask; 1707ec681f3Smrg 1717ec681f3Smrg uint64_t value_orig = value; 1727ec681f3Smrg if (!ti) 1737ec681f3Smrg goto failhex; 1747ec681f3Smrg value = (value & typeinfo_mask(ti)) >> ti->low; 1757ec681f3Smrg value <<= ti->shr; 1767ec681f3Smrg 1777ec681f3Smrg switch (ti->type) { 1787ec681f3Smrg case RNN_TTYPE_ENUM: 1797ec681f3Smrg vals = ti->eenum->vals; 1807ec681f3Smrg valsnum = ti->eenum->valsnum; 1817ec681f3Smrg goto doenum; 1827ec681f3Smrg case RNN_TTYPE_INLINE_ENUM: 1837ec681f3Smrg vals = ti->vals; 1847ec681f3Smrg valsnum = ti->valsnum; 1857ec681f3Smrg goto doenum; 1867ec681f3Smrg doenum: 1877ec681f3Smrg ctmp = rnndec_decode_enum_val(ctx, vals, valsnum, value); 1887ec681f3Smrg if (ctmp) { 1897ec681f3Smrg asprintf (&res, "%s%s%s", ctx->colors->eval, ctmp, ctx->colors->reset); 1907ec681f3Smrg if (ti->addvariant) { 1917ec681f3Smrg rnndec_varadd(ctx, ti->eenum->name, ctmp); 1927ec681f3Smrg } 1937ec681f3Smrg break; 1947ec681f3Smrg } 1957ec681f3Smrg goto failhex; 1967ec681f3Smrg case RNN_TTYPE_BITSET: 1977ec681f3Smrg bitfields = ti->ebitset->bitfields; 1987ec681f3Smrg bitfieldsnum = ti->ebitset->bitfieldsnum; 1997ec681f3Smrg goto dobitset; 2007ec681f3Smrg case RNN_TTYPE_INLINE_BITSET: 2017ec681f3Smrg bitfields = ti->bitfields; 2027ec681f3Smrg bitfieldsnum = ti->bitfieldsnum; 2037ec681f3Smrg goto dobitset; 2047ec681f3Smrg dobitset: 2057ec681f3Smrg mask = 0; 2067ec681f3Smrg for (i = 0; i < bitfieldsnum; i++) { 2077ec681f3Smrg if (!rnndec_varmatch(ctx, &bitfields[i]->varinfo)) 2087ec681f3Smrg continue; 2097ec681f3Smrg uint64_t type_mask = typeinfo_mask(&bitfields[i]->typeinfo); 2107ec681f3Smrg if (((value & type_mask) == 0) && is_unknown(bitfields[i]->name)) 2117ec681f3Smrg continue; 2127ec681f3Smrg mask |= type_mask; 2137ec681f3Smrg if (bitfields[i]->typeinfo.type == RNN_TTYPE_BOOLEAN) { 2147ec681f3Smrg const char *color = is_unknown(bitfields[i]->name) ? 2157ec681f3Smrg ctx->colors->err : ctx->colors->mod; 2167ec681f3Smrg if (value & type_mask) { 2177ec681f3Smrg if (!res) 2187ec681f3Smrg asprintf (&res, "%s%s%s", color, bitfields[i]->name, ctx->colors->reset); 2197ec681f3Smrg else { 2207ec681f3Smrg asprintf (&tmp, "%s | %s%s%s", res, color, bitfields[i]->name, ctx->colors->reset); 2217ec681f3Smrg free(res); 2227ec681f3Smrg res = tmp; 2237ec681f3Smrg } 2247ec681f3Smrg } 2257ec681f3Smrg continue; 2267ec681f3Smrg } 2277ec681f3Smrg char *subval; 2287ec681f3Smrg if (is_unknown(bitfields[i]->name) && (bitfields[i]->typeinfo.type != RNN_TTYPE_A3XX_REGID)) { 2297ec681f3Smrg uint64_t field_val = value & type_mask; 2307ec681f3Smrg field_val = (field_val & typeinfo_mask(&bitfields[i]->typeinfo)) >> bitfields[i]->typeinfo.low; 2317ec681f3Smrg field_val <<= bitfields[i]->typeinfo.shr; 2327ec681f3Smrg asprintf (&subval, "%s%#"PRIx64"%s", ctx->colors->err, field_val, ctx->colors->reset); 2337ec681f3Smrg } else { 2347ec681f3Smrg subval = rnndec_decodeval(ctx, &bitfields[i]->typeinfo, value & type_mask); 2357ec681f3Smrg } 2367ec681f3Smrg if (!res) 2377ec681f3Smrg asprintf (&res, "%s%s%s = %s", ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval); 2387ec681f3Smrg else { 2397ec681f3Smrg asprintf (&tmp, "%s | %s%s%s = %s", res, ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval); 2407ec681f3Smrg free(res); 2417ec681f3Smrg res = tmp; 2427ec681f3Smrg } 2437ec681f3Smrg free(subval); 2447ec681f3Smrg } 2457ec681f3Smrg if (value & ~mask) { 2467ec681f3Smrg if (!res) 2477ec681f3Smrg asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->err, value & ~mask, ctx->colors->reset); 2487ec681f3Smrg else { 2497ec681f3Smrg asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value & ~mask, ctx->colors->reset); 2507ec681f3Smrg free(res); 2517ec681f3Smrg res = tmp; 2527ec681f3Smrg } 2537ec681f3Smrg } 2547ec681f3Smrg if (!res) 2557ec681f3Smrg asprintf (&res, "%s0%s", ctx->colors->num, ctx->colors->reset); 2567ec681f3Smrg asprintf (&tmp, "{ %s }", res); 2577ec681f3Smrg free(res); 2587ec681f3Smrg return tmp; 2597ec681f3Smrg case RNN_TTYPE_SPECTYPE: 2607ec681f3Smrg return rnndec_decodeval(ctx, &ti->spectype->typeinfo, value); 2617ec681f3Smrg case RNN_TTYPE_HEX: 2627ec681f3Smrg asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset); 2637ec681f3Smrg break; 2647ec681f3Smrg case RNN_TTYPE_FIXED: 2657ec681f3Smrg if (value & UINT64_C(1) << (width-1)) { 2667ec681f3Smrg asprintf (&res, "%s-%lf%s", ctx->colors->num, 2677ec681f3Smrg ((double)((UINT64_C(1) << width) - value)) / ((double)(1 << ti->radix)), 2687ec681f3Smrg ctx->colors->reset); 2697ec681f3Smrg break; 2707ec681f3Smrg } 2717ec681f3Smrg FALLTHROUGH; 2727ec681f3Smrg case RNN_TTYPE_UFIXED: 2737ec681f3Smrg asprintf (&res, "%s%lf%s", ctx->colors->num, 2747ec681f3Smrg ((double)value) / ((double)(1LL << ti->radix)), 2757ec681f3Smrg ctx->colors->reset); 2767ec681f3Smrg break; 2777ec681f3Smrg case RNN_TTYPE_A3XX_REGID: 2787ec681f3Smrg asprintf (&res, "%sr%"PRIu64".%c%s", ctx->colors->num, (value >> 2), "xyzw"[value & 0x3], ctx->colors->reset); 2797ec681f3Smrg break; 2807ec681f3Smrg case RNN_TTYPE_UINT: 2817ec681f3Smrg asprintf (&res, "%s%"PRIu64"%s", ctx->colors->num, value, ctx->colors->reset); 2827ec681f3Smrg break; 2837ec681f3Smrg case RNN_TTYPE_INT: 2847ec681f3Smrg if (value & UINT64_C(1) << (width-1)) 2857ec681f3Smrg asprintf (&res, "%s-%"PRIi64"%s", ctx->colors->num, (UINT64_C(1) << width) - value, ctx->colors->reset); 2867ec681f3Smrg else 2877ec681f3Smrg asprintf (&res, "%s%"PRIi64"%s", ctx->colors->num, value, ctx->colors->reset); 2887ec681f3Smrg break; 2897ec681f3Smrg case RNN_TTYPE_BOOLEAN: 2907ec681f3Smrg if (value == 0) { 2917ec681f3Smrg asprintf (&res, "%sFALSE%s", ctx->colors->eval, ctx->colors->reset); 2927ec681f3Smrg } else if (value == 1) { 2937ec681f3Smrg asprintf (&res, "%sTRUE%s", ctx->colors->eval, ctx->colors->reset); 2947ec681f3Smrg } 2957ec681f3Smrg break; 2967ec681f3Smrg case RNN_TTYPE_FLOAT: { 2977ec681f3Smrg union { uint64_t i; float f; double d; } val; 2987ec681f3Smrg val.i = value; 2997ec681f3Smrg if (width == 64) 3007ec681f3Smrg asprintf(&res, "%s%f%s", ctx->colors->num, 3017ec681f3Smrg val.d, ctx->colors->reset); 3027ec681f3Smrg else if (width == 32) 3037ec681f3Smrg asprintf(&res, "%s%f%s", ctx->colors->num, 3047ec681f3Smrg val.f, ctx->colors->reset); 3057ec681f3Smrg else if (width == 16) 3067ec681f3Smrg asprintf(&res, "%s%f%s", ctx->colors->num, 3077ec681f3Smrg float16(value), ctx->colors->reset); 3087ec681f3Smrg else 3097ec681f3Smrg goto failhex; 3107ec681f3Smrg 3117ec681f3Smrg break; 3127ec681f3Smrg } 3137ec681f3Smrg failhex: 3147ec681f3Smrg default: 3157ec681f3Smrg asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset); 3167ec681f3Smrg break; 3177ec681f3Smrg } 3187ec681f3Smrg if (value_orig & ~typeinfo_mask(ti)) { 3197ec681f3Smrg asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value_orig & ~typeinfo_mask(ti), ctx->colors->reset); 3207ec681f3Smrg free(res); 3217ec681f3Smrg res = tmp; 3227ec681f3Smrg } 3237ec681f3Smrg return res; 3247ec681f3Smrg} 3257ec681f3Smrg 3267ec681f3Smrgstatic char *appendidx (struct rnndeccontext *ctx, char *name, uint64_t idx, struct rnnenum *index) { 3277ec681f3Smrg char *res; 3287ec681f3Smrg const char *index_name = NULL; 3297ec681f3Smrg 3307ec681f3Smrg if (index) 3317ec681f3Smrg index_name = rnndec_decode_enum_val(ctx, index->vals, index->valsnum, idx); 3327ec681f3Smrg 3337ec681f3Smrg if (index_name) 3347ec681f3Smrg asprintf (&res, "%s[%s%s%s]", name, ctx->colors->eval, index_name, ctx->colors->reset); 3357ec681f3Smrg else 3367ec681f3Smrg asprintf (&res, "%s[%s%#"PRIx64"%s]", name, ctx->colors->num, idx, ctx->colors->reset); 3377ec681f3Smrg 3387ec681f3Smrg free (name); 3397ec681f3Smrg return res; 3407ec681f3Smrg} 3417ec681f3Smrg 3427ec681f3Smrg/* This could probably be made to work for stripes too.. */ 3437ec681f3Smrgstatic int get_array_idx_offset(struct rnndelem *elem, uint64_t addr, uint64_t *idx, uint64_t *offset) 3447ec681f3Smrg{ 3457ec681f3Smrg if (elem->offsets) { 3467ec681f3Smrg int i; 3477ec681f3Smrg for (i = 0; i < elem->offsetsnum; i++) { 3487ec681f3Smrg uint64_t o = elem->offsets[i]; 3497ec681f3Smrg if ((o <= addr) && (addr < (o + elem->stride))) { 3507ec681f3Smrg *idx = i; 3517ec681f3Smrg *offset = addr - o; 3527ec681f3Smrg return 0; 3537ec681f3Smrg } 3547ec681f3Smrg } 3557ec681f3Smrg return -1; 3567ec681f3Smrg } else { 3577ec681f3Smrg if (addr < elem->offset) 3587ec681f3Smrg return -1; 3597ec681f3Smrg 3607ec681f3Smrg *idx = (addr - elem->offset) / elem->stride; 3617ec681f3Smrg *offset = (addr - elem->offset) % elem->stride; 3627ec681f3Smrg 3637ec681f3Smrg if (elem->length && (*idx >= elem->length)) 3647ec681f3Smrg return -1; 3657ec681f3Smrg 3667ec681f3Smrg return 0; 3677ec681f3Smrg } 3687ec681f3Smrg} 3697ec681f3Smrg 3707ec681f3Smrgstatic struct rnndecaddrinfo *trymatch (struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum, uint64_t addr, int write, int dwidth, uint64_t *indices, int indicesnum) { 3717ec681f3Smrg struct rnndecaddrinfo *res; 3727ec681f3Smrg int i, j; 3737ec681f3Smrg for (i = 0; i < elemsnum; i++) { 3747ec681f3Smrg if (!rnndec_varmatch(ctx, &elems[i]->varinfo)) 3757ec681f3Smrg continue; 3767ec681f3Smrg uint64_t offset, idx; 3777ec681f3Smrg char *tmp, *name; 3787ec681f3Smrg switch (elems[i]->type) { 3797ec681f3Smrg case RNN_ETYPE_REG: 3807ec681f3Smrg if (addr < elems[i]->offset) 3817ec681f3Smrg break; 3827ec681f3Smrg if (elems[i]->stride) { 3837ec681f3Smrg idx = (addr-elems[i]->offset)/elems[i]->stride; 3847ec681f3Smrg offset = (addr-elems[i]->offset)%elems[i]->stride; 3857ec681f3Smrg } else { 3867ec681f3Smrg idx = 0; 3877ec681f3Smrg offset = addr-elems[i]->offset; 3887ec681f3Smrg } 3897ec681f3Smrg if (offset >= elems[i]->width/dwidth) 3907ec681f3Smrg break; 3917ec681f3Smrg if (elems[i]->length && idx >= elems[i]->length) 3927ec681f3Smrg break; 3937ec681f3Smrg res = calloc (sizeof *res, 1); 3947ec681f3Smrg res->typeinfo = &elems[i]->typeinfo; 3957ec681f3Smrg res->width = elems[i]->width; 3967ec681f3Smrg asprintf (&res->name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset); 3977ec681f3Smrg for (j = 0; j < indicesnum; j++) 3987ec681f3Smrg res->name = appendidx(ctx, res->name, indices[j], NULL); 3997ec681f3Smrg if (elems[i]->length != 1) 4007ec681f3Smrg res->name = appendidx(ctx, res->name, idx, elems[i]->index); 4017ec681f3Smrg if (offset) { 4027ec681f3Smrg /* use _HI suffix for addresses */ 4037ec681f3Smrg if (offset == 1 && 4047ec681f3Smrg (!strcmp(res->typeinfo->name, "address") || 4057ec681f3Smrg !strcmp(res->typeinfo->name, "waddress"))) { 4067ec681f3Smrg asprintf (&tmp, "%s_HI", res->name); 4077ec681f3Smrg } else { 4087ec681f3Smrg asprintf (&tmp, "%s+%s%#"PRIx64"%s", res->name, ctx->colors->err, offset, ctx->colors->reset); 4097ec681f3Smrg } 4107ec681f3Smrg free(res->name); 4117ec681f3Smrg res->name = tmp; 4127ec681f3Smrg } 4137ec681f3Smrg return res; 4147ec681f3Smrg case RNN_ETYPE_STRIPE: 4157ec681f3Smrg for (idx = 0; idx < elems[i]->length || !elems[i]->length; idx++) { 4167ec681f3Smrg if (addr < elems[i]->offset + elems[i]->stride * idx) 4177ec681f3Smrg break; 4187ec681f3Smrg offset = addr - (elems[i]->offset + elems[i]->stride * idx); 4197ec681f3Smrg int extraidx = (elems[i]->length != 1); 4207ec681f3Smrg int nindnum = (elems[i]->name ? 0 : indicesnum + extraidx); 4217ec681f3Smrg uint64_t nind[MAX2(nindnum, 1)]; 4227ec681f3Smrg if (!elems[i]->name) { 4237ec681f3Smrg for (j = 0; j < indicesnum; j++) 4247ec681f3Smrg nind[j] = indices[j]; 4257ec681f3Smrg if (extraidx) 4267ec681f3Smrg nind[indicesnum] = idx; 4277ec681f3Smrg } 4287ec681f3Smrg res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, nind, nindnum); 4297ec681f3Smrg if (!res) 4307ec681f3Smrg continue; 4317ec681f3Smrg if (!elems[i]->name) 4327ec681f3Smrg return res; 4337ec681f3Smrg asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset); 4347ec681f3Smrg for (j = 0; j < indicesnum; j++) 4357ec681f3Smrg name = appendidx(ctx, name, indices[j], NULL); 4367ec681f3Smrg if (elems[i]->length != 1) 4377ec681f3Smrg name = appendidx(ctx, name, idx, elems[i]->index); 4387ec681f3Smrg asprintf (&tmp, "%s.%s", name, res->name); 4397ec681f3Smrg free(name); 4407ec681f3Smrg free(res->name); 4417ec681f3Smrg res->name = tmp; 4427ec681f3Smrg return res; 4437ec681f3Smrg } 4447ec681f3Smrg break; 4457ec681f3Smrg case RNN_ETYPE_ARRAY: 4467ec681f3Smrg if (get_array_idx_offset(elems[i], addr, &idx, &offset)) 4477ec681f3Smrg break; 4487ec681f3Smrg asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset); 4497ec681f3Smrg for (j = 0; j < indicesnum; j++) 4507ec681f3Smrg name = appendidx(ctx, name, indices[j], NULL); 4517ec681f3Smrg if (elems[i]->length != 1) 4527ec681f3Smrg name = appendidx(ctx, name, idx, elems[i]->index); 4537ec681f3Smrg if ((res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, 0, 0))) { 4547ec681f3Smrg asprintf (&tmp, "%s.%s", name, res->name); 4557ec681f3Smrg free(name); 4567ec681f3Smrg free(res->name); 4577ec681f3Smrg res->name = tmp; 4587ec681f3Smrg return res; 4597ec681f3Smrg } 4607ec681f3Smrg res = calloc (sizeof *res, 1); 4617ec681f3Smrg asprintf (&tmp, "%s+%s%#"PRIx64"%s", name, ctx->colors->err, offset, ctx->colors->reset); 4627ec681f3Smrg free(name); 4637ec681f3Smrg res->name = tmp; 4647ec681f3Smrg return res; 4657ec681f3Smrg default: 4667ec681f3Smrg break; 4677ec681f3Smrg } 4687ec681f3Smrg } 4697ec681f3Smrg return 0; 4707ec681f3Smrg} 4717ec681f3Smrg 4727ec681f3Smrgint rnndec_checkaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) { 4737ec681f3Smrg struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0); 4747ec681f3Smrg if (res) { 4757ec681f3Smrg free(res->name); 4767ec681f3Smrg free(res); 4777ec681f3Smrg } 4787ec681f3Smrg return res != NULL; 4797ec681f3Smrg} 4807ec681f3Smrg 4817ec681f3Smrgstruct rnndecaddrinfo *rnndec_decodeaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) { 4827ec681f3Smrg struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0); 4837ec681f3Smrg if (res) 4847ec681f3Smrg return res; 4857ec681f3Smrg res = calloc (sizeof *res, 1); 4867ec681f3Smrg asprintf (&res->name, "%s%#"PRIx64"%s", ctx->colors->err, addr, ctx->colors->reset); 4877ec681f3Smrg return res; 4887ec681f3Smrg} 4897ec681f3Smrg 4907ec681f3Smrgstatic unsigned tryreg(struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum, 4917ec681f3Smrg int dwidth, const char *name, uint64_t *offset) 4927ec681f3Smrg{ 4937ec681f3Smrg int i; 4947ec681f3Smrg unsigned ret; 4957ec681f3Smrg const char *suffix = strchr(name, '['); 4967ec681f3Smrg unsigned n = suffix ? (suffix - name) : strlen(name); 4977ec681f3Smrg const char *dotsuffix = strchr(name, '.'); 4987ec681f3Smrg unsigned dotn = dotsuffix ? (dotsuffix - name) : strlen(name); 4997ec681f3Smrg 5007ec681f3Smrg const char *child = NULL; 5017ec681f3Smrg unsigned idx = 0; 5027ec681f3Smrg 5037ec681f3Smrg if (suffix) { 5047ec681f3Smrg const char *tmp = strchr(suffix, ']'); 5057ec681f3Smrg idx = strtol(suffix+1, NULL, 0); 5067ec681f3Smrg child = tmp+2; 5077ec681f3Smrg } 5087ec681f3Smrg 5097ec681f3Smrg for (i = 0; i < elemsnum; i++) { 5107ec681f3Smrg struct rnndelem *elem = elems[i]; 5117ec681f3Smrg if (!rnndec_varmatch(ctx, &elem->varinfo)) 5127ec681f3Smrg continue; 5137ec681f3Smrg int match = elem->name && (strlen(elem->name) == n) && !strncmp(elem->name, name, n); 5147ec681f3Smrg switch (elem->type) { 5157ec681f3Smrg case RNN_ETYPE_REG: 5167ec681f3Smrg if (match) { 5177ec681f3Smrg assert(!suffix); 5187ec681f3Smrg *offset = elem->offset; 5197ec681f3Smrg return 1; 5207ec681f3Smrg } 5217ec681f3Smrg break; 5227ec681f3Smrg case RNN_ETYPE_STRIPE: 5237ec681f3Smrg if (elem->name) { 5247ec681f3Smrg if (!dotsuffix) 5257ec681f3Smrg break; 5267ec681f3Smrg if (strlen(elem->name) != dotn || strncmp(elem->name, name, dotn)) 5277ec681f3Smrg break; 5287ec681f3Smrg } 5297ec681f3Smrg ret = tryreg(ctx, elem->subelems, elem->subelemsnum, dwidth, 5307ec681f3Smrg elem->name ? dotsuffix : name, offset); 5317ec681f3Smrg if (ret) 5327ec681f3Smrg return 1; 5337ec681f3Smrg break; 5347ec681f3Smrg case RNN_ETYPE_ARRAY: 5357ec681f3Smrg if (match) { 5367ec681f3Smrg assert(suffix); 5377ec681f3Smrg ret = tryreg(ctx, elem->subelems, elem->subelemsnum, dwidth, child, offset); 5387ec681f3Smrg if (ret) { 5397ec681f3Smrg *offset += elem->offset + (idx * elem->stride); 5407ec681f3Smrg return 1; 5417ec681f3Smrg } 5427ec681f3Smrg } 5437ec681f3Smrg break; 5447ec681f3Smrg default: 5457ec681f3Smrg break; 5467ec681f3Smrg } 5477ec681f3Smrg } 5487ec681f3Smrg return 0; 5497ec681f3Smrg} 5507ec681f3Smrg 5517ec681f3Smrguint64_t rnndec_decodereg(struct rnndeccontext *ctx, struct rnndomain *domain, const char *name) 5527ec681f3Smrg{ 5537ec681f3Smrg uint64_t offset; 5547ec681f3Smrg if (tryreg(ctx, domain->subelems, domain->subelemsnum, domain->width, name, &offset)) { 5557ec681f3Smrg return offset; 5567ec681f3Smrg } else { 5577ec681f3Smrg return 0; 5587ec681f3Smrg } 5597ec681f3Smrg} 560