Path: blob/21.2-virgl/src/broadcom/cle/v3d_decoder.c
4560 views
/*1* Copyright © 2016 Intel Corporation2* Copyright © 2017 Broadcom3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21* IN THE SOFTWARE.22*/2324#include "v3d_decoder.h"2526#include <stdio.h>27#include <stdlib.h>28#include <stdbool.h>29#include <stdint.h>30#include <stdarg.h>31#include <string.h>32#ifdef WITH_LIBEXPAT33#include <expat.h>34#endif35#include <inttypes.h>36#include <zlib.h>3738#include <util/macros.h>39#include <util/ralloc.h>40#include <util/u_debug.h>4142#include "v3d_packet_helpers.h"43#include "v3d_xml.h"44#include "broadcom/clif/clif_private.h"4546struct v3d_spec {47uint32_t ver;4849int ncommands;50struct v3d_group *commands[256];51int nstructs;52struct v3d_group *structs[256];53int nregisters;54struct v3d_group *registers[256];55int nenums;56struct v3d_enum *enums[256];57};5859#ifdef WITH_LIBEXPAT6061struct location {62const char *filename;63int line_number;64};6566struct parser_context {67XML_Parser parser;68const struct v3d_device_info *devinfo;69int foo;70struct location loc;7172struct v3d_group *group;73struct v3d_enum *enoom;7475int nvalues;76struct v3d_value *values[256];7778struct v3d_spec *spec;7980int parse_depth;81int parse_skip_depth;82};8384#endif /* WITH_LIBEXPAT */8586const char *87v3d_group_get_name(struct v3d_group *group)88{89return group->name;90}9192uint8_t93v3d_group_get_opcode(struct v3d_group *group)94{95return group->opcode;96}9798struct v3d_group *99v3d_spec_find_struct(struct v3d_spec *spec, const char *name)100{101for (int i = 0; i < spec->nstructs; i++)102if (strcmp(spec->structs[i]->name, name) == 0)103return spec->structs[i];104105return NULL;106}107108struct v3d_group *109v3d_spec_find_register(struct v3d_spec *spec, uint32_t offset)110{111for (int i = 0; i < spec->nregisters; i++)112if (spec->registers[i]->register_offset == offset)113return spec->registers[i];114115return NULL;116}117118struct v3d_group *119v3d_spec_find_register_by_name(struct v3d_spec *spec, const char *name)120{121for (int i = 0; i < spec->nregisters; i++) {122if (strcmp(spec->registers[i]->name, name) == 0)123return spec->registers[i];124}125126return NULL;127}128129struct v3d_enum *130v3d_spec_find_enum(struct v3d_spec *spec, const char *name)131{132for (int i = 0; i < spec->nenums; i++)133if (strcmp(spec->enums[i]->name, name) == 0)134return spec->enums[i];135136return NULL;137}138139#ifdef WITH_LIBEXPAT140141static void __attribute__((noreturn))142fail(struct location *loc, const char *msg, ...)143{144va_list ap;145146va_start(ap, msg);147fprintf(stderr, "%s:%d: error: ",148loc->filename, loc->line_number);149vfprintf(stderr, msg, ap);150fprintf(stderr, "\n");151va_end(ap);152exit(EXIT_FAILURE);153}154155static void *156fail_on_null(void *p)157{158if (p == NULL) {159fprintf(stderr, "aubinator: out of memory\n");160exit(EXIT_FAILURE);161}162163return p;164}165166static char *167xstrdup(const char *s)168{169return fail_on_null(strdup(s));170}171172static void *173zalloc(size_t s)174{175return calloc(s, 1);176}177178static void *179xzalloc(size_t s)180{181return fail_on_null(zalloc(s));182}183184/* We allow fields to have either a bit index, or append "b" for a byte index.185*/186static bool187is_byte_offset(const char *value)188{189return value[strlen(value) - 1] == 'b';190}191192static void193get_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count,194uint32_t *size, bool *variable)195{196char *p;197int i;198199for (i = 0; atts[i]; i += 2) {200if (strcmp(atts[i], "count") == 0) {201*count = strtoul(atts[i + 1], &p, 0);202if (*count == 0)203*variable = true;204} else if (strcmp(atts[i], "start") == 0) {205*offset = strtoul(atts[i + 1], &p, 0);206} else if (strcmp(atts[i], "size") == 0) {207*size = strtoul(atts[i + 1], &p, 0);208}209}210return;211}212213static struct v3d_group *214create_group(struct parser_context *ctx,215const char *name,216const char **atts,217struct v3d_group *parent)218{219struct v3d_group *group;220221group = xzalloc(sizeof(*group));222if (name)223group->name = xstrdup(name);224225group->spec = ctx->spec;226group->group_offset = 0;227group->group_count = 0;228group->variable = false;229230if (parent) {231group->parent = parent;232get_group_offset_count(atts,233&group->group_offset,234&group->group_count,235&group->group_size,236&group->variable);237}238239return group;240}241242static struct v3d_enum *243create_enum(struct parser_context *ctx, const char *name, const char **atts)244{245struct v3d_enum *e;246247e = xzalloc(sizeof(*e));248if (name)249e->name = xstrdup(name);250251e->nvalues = 0;252253return e;254}255256static void257get_register_offset(const char **atts, uint32_t *offset)258{259char *p;260int i;261262for (i = 0; atts[i]; i += 2) {263if (strcmp(atts[i], "num") == 0)264*offset = strtoul(atts[i + 1], &p, 0);265}266return;267}268269static void270get_start_end_pos(int *start, int *end)271{272/* start value has to be mod with 32 as we need the relative273* start position in the first DWord. For the end position, add274* the length of the field to the start position to get the275* relative postion in the 64 bit address.276*/277if (*end - *start > 32) {278int len = *end - *start;279*start = *start % 32;280*end = *start + len;281} else {282*start = *start % 32;283*end = *end % 32;284}285286return;287}288289static inline uint64_t290mask(int start, int end)291{292uint64_t v;293294v = ~0ULL >> (63 - end + start);295296return v << start;297}298299static inline uint64_t300field(uint64_t value, int start, int end)301{302get_start_end_pos(&start, &end);303return (value & mask(start, end)) >> (start);304}305306static inline uint64_t307field_address(uint64_t value, int start, int end)308{309/* no need to right shift for address/offset */310get_start_end_pos(&start, &end);311return (value & mask(start, end));312}313314static struct v3d_type315string_to_type(struct parser_context *ctx, const char *s)316{317int i, f;318struct v3d_group *g;319struct v3d_enum *e;320321if (strcmp(s, "int") == 0)322return (struct v3d_type) { .kind = V3D_TYPE_INT };323else if (strcmp(s, "uint") == 0)324return (struct v3d_type) { .kind = V3D_TYPE_UINT };325else if (strcmp(s, "bool") == 0)326return (struct v3d_type) { .kind = V3D_TYPE_BOOL };327else if (strcmp(s, "float") == 0)328return (struct v3d_type) { .kind = V3D_TYPE_FLOAT };329else if (strcmp(s, "f187") == 0)330return (struct v3d_type) { .kind = V3D_TYPE_F187 };331else if (strcmp(s, "address") == 0)332return (struct v3d_type) { .kind = V3D_TYPE_ADDRESS };333else if (strcmp(s, "offset") == 0)334return (struct v3d_type) { .kind = V3D_TYPE_OFFSET };335else if (sscanf(s, "u%d.%d", &i, &f) == 2)336return (struct v3d_type) { .kind = V3D_TYPE_UFIXED, .i = i, .f = f };337else if (sscanf(s, "s%d.%d", &i, &f) == 2)338return (struct v3d_type) { .kind = V3D_TYPE_SFIXED, .i = i, .f = f };339else if (g = v3d_spec_find_struct(ctx->spec, s), g != NULL)340return (struct v3d_type) { .kind = V3D_TYPE_STRUCT, .v3d_struct = g };341else if (e = v3d_spec_find_enum(ctx->spec, s), e != NULL)342return (struct v3d_type) { .kind = V3D_TYPE_ENUM, .v3d_enum = e };343else if (strcmp(s, "mbo") == 0)344return (struct v3d_type) { .kind = V3D_TYPE_MBO };345else346fail(&ctx->loc, "invalid type: %s", s);347}348349static struct v3d_field *350create_field(struct parser_context *ctx, const char **atts)351{352struct v3d_field *field;353char *p;354int i;355uint32_t size = 0;356357field = xzalloc(sizeof(*field));358359for (i = 0; atts[i]; i += 2) {360if (strcmp(atts[i], "name") == 0)361field->name = xstrdup(atts[i + 1]);362else if (strcmp(atts[i], "start") == 0) {363field->start = strtoul(atts[i + 1], &p, 0);364if (is_byte_offset(atts[i + 1]))365field->start *= 8;366} else if (strcmp(atts[i], "end") == 0) {367field->end = strtoul(atts[i + 1], &p, 0) - 1;368if (is_byte_offset(atts[i + 1]))369field->end *= 8;370} else if (strcmp(atts[i], "size") == 0) {371size = strtoul(atts[i + 1], &p, 0);372if (is_byte_offset(atts[i + 1]))373size *= 8;374} else if (strcmp(atts[i], "type") == 0)375field->type = string_to_type(ctx, atts[i + 1]);376else if (strcmp(atts[i], "default") == 0) {377field->has_default = true;378field->default_value = strtoul(atts[i + 1], &p, 0);379} else if (strcmp(atts[i], "minus_one") == 0) {380assert(strcmp(atts[i + 1], "true") == 0);381field->minus_one = true;382}383}384385if (size)386field->end = field->start + size - 1;387388return field;389}390391static struct v3d_value *392create_value(struct parser_context *ctx, const char **atts)393{394struct v3d_value *value = xzalloc(sizeof(*value));395396for (int i = 0; atts[i]; i += 2) {397if (strcmp(atts[i], "name") == 0)398value->name = xstrdup(atts[i + 1]);399else if (strcmp(atts[i], "value") == 0)400value->value = strtoul(atts[i + 1], NULL, 0);401}402403return value;404}405406static void407create_and_append_field(struct parser_context *ctx,408const char **atts)409{410if (ctx->group->nfields == ctx->group->fields_size) {411ctx->group->fields_size = MAX2(ctx->group->fields_size * 2, 2);412ctx->group->fields =413(struct v3d_field **) realloc(ctx->group->fields,414sizeof(ctx->group->fields[0]) *415ctx->group->fields_size);416}417418ctx->group->fields[ctx->group->nfields++] = create_field(ctx, atts);419}420421static void422set_group_opcode(struct v3d_group *group, const char **atts)423{424char *p;425int i;426427for (i = 0; atts[i]; i += 2) {428if (strcmp(atts[i], "code") == 0)429group->opcode = strtoul(atts[i + 1], &p, 0);430}431return;432}433434static bool435ver_in_range(int ver, int min_ver, int max_ver)436{437return ((min_ver == 0 || ver >= min_ver) &&438(max_ver == 0 || ver <= max_ver));439}440441static bool442skip_if_ver_mismatch(struct parser_context *ctx, int min_ver, int max_ver)443{444if (!ctx->parse_skip_depth && !ver_in_range(ctx->devinfo->ver,445min_ver, max_ver)) {446assert(ctx->parse_depth != 0);447ctx->parse_skip_depth = ctx->parse_depth;448}449450return ctx->parse_skip_depth;451}452453static void454start_element(void *data, const char *element_name, const char **atts)455{456struct parser_context *ctx = data;457int i;458const char *name = NULL;459const char *ver = NULL;460int min_ver = 0;461int max_ver = 0;462463ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);464465for (i = 0; atts[i]; i += 2) {466if (strcmp(atts[i], "shortname") == 0)467name = atts[i + 1];468else if (strcmp(atts[i], "name") == 0 && !name)469name = atts[i + 1];470else if (strcmp(atts[i], "gen") == 0)471ver = atts[i + 1];472else if (strcmp(atts[i], "min_ver") == 0)473min_ver = strtoul(atts[i + 1], NULL, 0);474else if (strcmp(atts[i], "max_ver") == 0)475max_ver = strtoul(atts[i + 1], NULL, 0);476}477478if (skip_if_ver_mismatch(ctx, min_ver, max_ver))479goto skip;480481if (strcmp(element_name, "vcxml") == 0) {482if (ver == NULL)483fail(&ctx->loc, "no ver given");484485/* Make sure that we picked an XML that matched our version.486*/487assert(ver_in_range(ctx->devinfo->ver, min_ver, max_ver));488489int major, minor;490int n = sscanf(ver, "%d.%d", &major, &minor);491if (n == 0)492fail(&ctx->loc, "invalid ver given: %s", ver);493if (n == 1)494minor = 0;495496ctx->spec->ver = major * 10 + minor;497} else if (strcmp(element_name, "packet") == 0 ||498strcmp(element_name, "struct") == 0) {499ctx->group = create_group(ctx, name, atts, NULL);500501if (strcmp(element_name, "packet") == 0)502set_group_opcode(ctx->group, atts);503} else if (strcmp(element_name, "register") == 0) {504ctx->group = create_group(ctx, name, atts, NULL);505get_register_offset(atts, &ctx->group->register_offset);506} else if (strcmp(element_name, "group") == 0) {507struct v3d_group *previous_group = ctx->group;508while (previous_group->next)509previous_group = previous_group->next;510511struct v3d_group *group = create_group(ctx, "", atts,512ctx->group);513previous_group->next = group;514ctx->group = group;515} else if (strcmp(element_name, "field") == 0) {516create_and_append_field(ctx, atts);517} else if (strcmp(element_name, "enum") == 0) {518ctx->enoom = create_enum(ctx, name, atts);519} else if (strcmp(element_name, "value") == 0) {520ctx->values[ctx->nvalues++] = create_value(ctx, atts);521assert(ctx->nvalues < ARRAY_SIZE(ctx->values));522}523524skip:525ctx->parse_depth++;526}527528static int529field_offset_compare(const void *a, const void *b)530{531return ((*(const struct v3d_field **)a)->start -532(*(const struct v3d_field **)b)->start);533}534535static void536end_element(void *data, const char *name)537{538struct parser_context *ctx = data;539struct v3d_spec *spec = ctx->spec;540541ctx->parse_depth--;542543if (ctx->parse_skip_depth) {544if (ctx->parse_skip_depth == ctx->parse_depth)545ctx->parse_skip_depth = 0;546return;547}548549if (strcmp(name, "packet") == 0 ||550strcmp(name, "struct") == 0 ||551strcmp(name, "register") == 0) {552struct v3d_group *group = ctx->group;553554ctx->group = ctx->group->parent;555556if (strcmp(name, "packet") == 0) {557spec->commands[spec->ncommands++] = group;558559/* V3D packet XML has the packet contents with offsets560* starting from the first bit after the opcode, to561* match the spec. Shift the fields up now.562*/563for (int i = 0; i < group->nfields; i++) {564group->fields[i]->start += 8;565group->fields[i]->end += 8;566}567}568else if (strcmp(name, "struct") == 0)569spec->structs[spec->nstructs++] = group;570else if (strcmp(name, "register") == 0)571spec->registers[spec->nregisters++] = group;572573/* Sort the fields in increasing offset order. The XML might574* be specified in any order, but we'll want to iterate from575* the bottom.576*/577qsort(group->fields, group->nfields, sizeof(*group->fields),578field_offset_compare);579580assert(spec->ncommands < ARRAY_SIZE(spec->commands));581assert(spec->nstructs < ARRAY_SIZE(spec->structs));582assert(spec->nregisters < ARRAY_SIZE(spec->registers));583} else if (strcmp(name, "group") == 0) {584ctx->group = ctx->group->parent;585} else if (strcmp(name, "field") == 0) {586assert(ctx->group->nfields > 0);587struct v3d_field *field = ctx->group->fields[ctx->group->nfields - 1];588size_t size = ctx->nvalues * sizeof(ctx->values[0]);589field->inline_enum.values = xzalloc(size);590field->inline_enum.nvalues = ctx->nvalues;591memcpy(field->inline_enum.values, ctx->values, size);592ctx->nvalues = 0;593} else if (strcmp(name, "enum") == 0) {594struct v3d_enum *e = ctx->enoom;595size_t size = ctx->nvalues * sizeof(ctx->values[0]);596e->values = xzalloc(size);597e->nvalues = ctx->nvalues;598memcpy(e->values, ctx->values, size);599ctx->nvalues = 0;600ctx->enoom = NULL;601spec->enums[spec->nenums++] = e;602}603}604605static void606character_data(void *data, const XML_Char *s, int len)607{608}609610static uint32_t zlib_inflate(const void *compressed_data,611uint32_t compressed_len,612void **out_ptr)613{614struct z_stream_s zstream;615void *out;616617memset(&zstream, 0, sizeof(zstream));618619zstream.next_in = (unsigned char *)compressed_data;620zstream.avail_in = compressed_len;621622if (inflateInit(&zstream) != Z_OK)623return 0;624625out = malloc(4096);626zstream.next_out = out;627zstream.avail_out = 4096;628629do {630switch (inflate(&zstream, Z_SYNC_FLUSH)) {631case Z_STREAM_END:632goto end;633case Z_OK:634break;635default:636inflateEnd(&zstream);637return 0;638}639640if (zstream.avail_out)641break;642643out = realloc(out, 2*zstream.total_out);644if (out == NULL) {645inflateEnd(&zstream);646return 0;647}648649zstream.next_out = (unsigned char *)out + zstream.total_out;650zstream.avail_out = zstream.total_out;651} while (1);652end:653inflateEnd(&zstream);654*out_ptr = out;655return zstream.total_out;656}657658#endif /* WITH_LIBEXPAT */659660struct v3d_spec *661v3d_spec_load(const struct v3d_device_info *devinfo)662{663struct v3d_spec *spec = calloc(1, sizeof(struct v3d_spec));664if (!spec)665return NULL;666667#ifdef WITH_LIBEXPAT668struct parser_context ctx;669void *buf;670uint8_t *text_data = NULL;671uint32_t text_offset = 0, text_length = 0;672ASSERTED uint32_t total_length;673674for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) {675if (i != 0) {676assert(genxml_files_table[i - 1].ver_10 <677genxml_files_table[i].ver_10);678}679680if (genxml_files_table[i].ver_10 <= devinfo->ver) {681text_offset = genxml_files_table[i].offset;682text_length = genxml_files_table[i].length;683}684}685686if (text_length == 0) {687fprintf(stderr, "unable to find gen (%u) data\n", devinfo->ver);688free(spec);689return NULL;690}691692memset(&ctx, 0, sizeof ctx);693ctx.parser = XML_ParserCreate(NULL);694ctx.devinfo = devinfo;695XML_SetUserData(ctx.parser, &ctx);696if (ctx.parser == NULL) {697fprintf(stderr, "failed to create parser\n");698free(spec);699return NULL;700}701702XML_SetElementHandler(ctx.parser, start_element, end_element);703XML_SetCharacterDataHandler(ctx.parser, character_data);704705ctx.spec = spec;706707total_length = zlib_inflate(compress_genxmls,708sizeof(compress_genxmls),709(void **) &text_data);710assert(text_offset + text_length <= total_length);711712buf = XML_GetBuffer(ctx.parser, text_length);713memcpy(buf, &text_data[text_offset], text_length);714715if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) {716fprintf(stderr,717"Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",718XML_GetCurrentLineNumber(ctx.parser),719XML_GetCurrentColumnNumber(ctx.parser),720XML_GetCurrentByteIndex(ctx.parser), text_length,721XML_ErrorString(XML_GetErrorCode(ctx.parser)));722XML_ParserFree(ctx.parser);723free(text_data);724free(spec);725return NULL;726}727728XML_ParserFree(ctx.parser);729free(text_data);730731return ctx.spec;732#else /* !WITH_LIBEXPAT */733debug_warn_once("CLIF dumping not supported due to missing libexpat");734return spec;735#endif /* !WITH_LIBEXPAT */736}737738struct v3d_group *739v3d_spec_find_instruction(struct v3d_spec *spec, const uint8_t *p)740{741uint8_t opcode = *p;742743for (int i = 0; i < spec->ncommands; i++) {744struct v3d_group *group = spec->commands[i];745746if (opcode != group->opcode)747continue;748749/* If there's a "sub-id" field, make sure that it matches the750* instruction being decoded.751*/752struct v3d_field *subid = NULL;753for (int j = 0; j < group->nfields; j++) {754struct v3d_field *field = group->fields[j];755if (strcmp(field->name, "sub-id") == 0) {756subid = field;757break;758}759}760761if (subid && (__gen_unpack_uint(p, subid->start, subid->end) !=762subid->default_value)) {763continue;764}765766return group;767}768769return NULL;770}771772/** Returns the size of a V3D packet. */773int774v3d_group_get_length(struct v3d_group *group)775{776int last_bit = 0;777for (int i = 0; i < group->nfields; i++) {778struct v3d_field *field = group->fields[i];779780last_bit = MAX2(last_bit, field->end);781}782return last_bit / 8 + 1;783}784785void786v3d_field_iterator_init(struct v3d_field_iterator *iter,787struct v3d_group *group,788const uint8_t *p)789{790memset(iter, 0, sizeof(*iter));791792iter->group = group;793iter->p = p;794}795796static const char *797v3d_get_enum_name(struct v3d_enum *e, uint64_t value)798{799for (int i = 0; i < e->nvalues; i++) {800if (e->values[i]->value == value) {801return e->values[i]->name;802}803}804return NULL;805}806807static bool808iter_more_fields(const struct v3d_field_iterator *iter)809{810return iter->field_iter < iter->group->nfields;811}812813static uint32_t814iter_group_offset_bits(const struct v3d_field_iterator *iter,815uint32_t group_iter)816{817return iter->group->group_offset + (group_iter *818iter->group->group_size);819}820821static bool822iter_more_groups(const struct v3d_field_iterator *iter)823{824if (iter->group->variable) {825return iter_group_offset_bits(iter, iter->group_iter + 1) <826(v3d_group_get_length(iter->group) * 8);827} else {828return (iter->group_iter + 1) < iter->group->group_count ||829iter->group->next != NULL;830}831}832833static void834iter_advance_group(struct v3d_field_iterator *iter)835{836if (iter->group->variable)837iter->group_iter++;838else {839if ((iter->group_iter + 1) < iter->group->group_count) {840iter->group_iter++;841} else {842iter->group = iter->group->next;843iter->group_iter = 0;844}845}846847iter->field_iter = 0;848}849850static bool851iter_advance_field(struct v3d_field_iterator *iter)852{853while (!iter_more_fields(iter)) {854if (!iter_more_groups(iter))855return false;856857iter_advance_group(iter);858}859860iter->field = iter->group->fields[iter->field_iter++];861if (iter->field->name)862snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name);863else864memset(iter->name, 0, sizeof(iter->name));865iter->offset = iter_group_offset_bits(iter, iter->group_iter) / 8 +866iter->field->start / 8;867iter->struct_desc = NULL;868869return true;870}871872bool873v3d_field_iterator_next(struct clif_dump *clif, struct v3d_field_iterator *iter)874{875if (!iter_advance_field(iter))876return false;877878const char *enum_name = NULL;879880int group_member_offset =881iter_group_offset_bits(iter, iter->group_iter);882int s = group_member_offset + iter->field->start;883int e = group_member_offset + iter->field->end;884885assert(!iter->field->minus_one ||886iter->field->type.kind == V3D_TYPE_INT ||887iter->field->type.kind == V3D_TYPE_UINT);888889switch (iter->field->type.kind) {890case V3D_TYPE_UNKNOWN:891case V3D_TYPE_INT: {892uint32_t value = __gen_unpack_sint(iter->p, s, e);893if (iter->field->minus_one)894value++;895snprintf(iter->value, sizeof(iter->value), "%d", value);896enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);897break;898}899case V3D_TYPE_UINT: {900uint32_t value = __gen_unpack_uint(iter->p, s, e);901if (iter->field->minus_one)902value++;903if (strcmp(iter->field->name, "Vec size") == 0 && value == 0)904value = 1 << (e - s + 1);905snprintf(iter->value, sizeof(iter->value), "%u", value);906enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);907break;908}909case V3D_TYPE_BOOL:910snprintf(iter->value, sizeof(iter->value), "%s",911__gen_unpack_uint(iter->p, s, e) ?912"1 /* true */" : "0 /* false */");913break;914case V3D_TYPE_FLOAT:915snprintf(iter->value, sizeof(iter->value), "%f",916__gen_unpack_float(iter->p, s, e));917break;918919case V3D_TYPE_F187:920snprintf(iter->value, sizeof(iter->value), "%f",921__gen_unpack_f187(iter->p, s, e));922break;923924case V3D_TYPE_ADDRESS: {925uint32_t addr =926__gen_unpack_uint(iter->p, s, e) << (31 - (e - s));927struct clif_bo *bo = clif_lookup_bo(clif, addr);928if (bo) {929snprintf(iter->value, sizeof(iter->value),930"[%s+0x%08x] /* 0x%08x */",931bo->name, addr - bo->offset, addr);932} else if (addr) {933snprintf(iter->value, sizeof(iter->value),934"/* XXX: BO unknown */ 0x%08x", addr);935} else {936snprintf(iter->value, sizeof(iter->value),937"[null]");938}939940break;941}942943case V3D_TYPE_OFFSET:944snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64,945__gen_unpack_uint(iter->p, s, e) << (31 - (e - s)));946break;947case V3D_TYPE_STRUCT:948snprintf(iter->value, sizeof(iter->value), "<struct %s>",949iter->field->type.v3d_struct->name);950iter->struct_desc =951v3d_spec_find_struct(iter->group->spec,952iter->field->type.v3d_struct->name);953break;954case V3D_TYPE_SFIXED:955if (clif->pretty) {956snprintf(iter->value, sizeof(iter->value), "%f",957__gen_unpack_sfixed(iter->p, s, e,958iter->field->type.f));959} else {960snprintf(iter->value, sizeof(iter->value), "%u",961(unsigned)__gen_unpack_uint(iter->p, s, e));962}963break;964case V3D_TYPE_UFIXED:965if (clif->pretty) {966snprintf(iter->value, sizeof(iter->value), "%f",967__gen_unpack_ufixed(iter->p, s, e,968iter->field->type.f));969} else {970snprintf(iter->value, sizeof(iter->value), "%u",971(unsigned)__gen_unpack_uint(iter->p, s, e));972}973break;974case V3D_TYPE_MBO:975break;976case V3D_TYPE_ENUM: {977uint32_t value = __gen_unpack_uint(iter->p, s, e);978snprintf(iter->value, sizeof(iter->value), "%d", value);979enum_name = v3d_get_enum_name(iter->field->type.v3d_enum, value);980break;981}982}983984if (strlen(iter->group->name) == 0) {985int length = strlen(iter->name);986snprintf(iter->name + length, sizeof(iter->name) - length,987"[%i]", iter->group_iter);988}989990if (enum_name) {991int length = strlen(iter->value);992snprintf(iter->value + length, sizeof(iter->value) - length,993" /* %s */", enum_name);994}995996return true;997}998999void1000v3d_print_group(struct clif_dump *clif, struct v3d_group *group,1001uint64_t offset, const uint8_t *p)1002{1003struct v3d_field_iterator iter;10041005v3d_field_iterator_init(&iter, group, p);1006while (v3d_field_iterator_next(clif, &iter)) {1007/* Clif parsing uses the packet name, and expects no1008* sub-id.1009*/1010if (strcmp(iter.field->name, "sub-id") == 0 ||1011strcmp(iter.field->name, "unused") == 0 ||1012strcmp(iter.field->name, "Pad") == 0)1013continue;10141015if (clif->pretty) {1016fprintf(clif->out, " %s: %s\n",1017iter.name, iter.value);1018} else {1019fprintf(clif->out, " /* %30s: */ %s\n",1020iter.name, iter.value);1021}1022if (iter.struct_desc) {1023uint64_t struct_offset = offset + iter.offset;1024v3d_print_group(clif, iter.struct_desc,1025struct_offset,1026&p[iter.offset]);1027}1028}1029}103010311032