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