1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2016 Intel Corporation 3b8e80941Smrg * Copyright © 2017 Broadcom 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg * to deal in the Software without restriction, including without limitation 8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 10b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg * 12b8e80941Smrg * The above copyright notice and this permission notice (including the next 13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg * Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22b8e80941Smrg * IN THE SOFTWARE. 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg#include <stdio.h> 26b8e80941Smrg#include <stdbool.h> 27b8e80941Smrg#include <stdint.h> 28b8e80941Smrg#include <stdarg.h> 29b8e80941Smrg#include <string.h> 30b8e80941Smrg#include <expat.h> 31b8e80941Smrg#include <inttypes.h> 32b8e80941Smrg#include <zlib.h> 33b8e80941Smrg 34b8e80941Smrg#include <util/macros.h> 35b8e80941Smrg#include <util/ralloc.h> 36b8e80941Smrg 37b8e80941Smrg#include "v3d_decoder.h" 38b8e80941Smrg#include "v3d_packet_helpers.h" 39b8e80941Smrg#include "v3d_xml.h" 40b8e80941Smrg#include "broadcom/clif/clif_private.h" 41b8e80941Smrg 42b8e80941Smrgstruct v3d_spec { 43b8e80941Smrg uint32_t ver; 44b8e80941Smrg 45b8e80941Smrg int ncommands; 46b8e80941Smrg struct v3d_group *commands[256]; 47b8e80941Smrg int nstructs; 48b8e80941Smrg struct v3d_group *structs[256]; 49b8e80941Smrg int nregisters; 50b8e80941Smrg struct v3d_group *registers[256]; 51b8e80941Smrg int nenums; 52b8e80941Smrg struct v3d_enum *enums[256]; 53b8e80941Smrg}; 54b8e80941Smrg 55b8e80941Smrgstruct location { 56b8e80941Smrg const char *filename; 57b8e80941Smrg int line_number; 58b8e80941Smrg}; 59b8e80941Smrg 60b8e80941Smrgstruct parser_context { 61b8e80941Smrg XML_Parser parser; 62b8e80941Smrg const struct v3d_device_info *devinfo; 63b8e80941Smrg int foo; 64b8e80941Smrg struct location loc; 65b8e80941Smrg 66b8e80941Smrg struct v3d_group *group; 67b8e80941Smrg struct v3d_enum *enoom; 68b8e80941Smrg 69b8e80941Smrg int nvalues; 70b8e80941Smrg struct v3d_value *values[256]; 71b8e80941Smrg 72b8e80941Smrg struct v3d_spec *spec; 73b8e80941Smrg 74b8e80941Smrg int parse_depth; 75b8e80941Smrg int parse_skip_depth; 76b8e80941Smrg}; 77b8e80941Smrg 78b8e80941Smrgconst char * 79b8e80941Smrgv3d_group_get_name(struct v3d_group *group) 80b8e80941Smrg{ 81b8e80941Smrg return group->name; 82b8e80941Smrg} 83b8e80941Smrg 84b8e80941Smrguint8_t 85b8e80941Smrgv3d_group_get_opcode(struct v3d_group *group) 86b8e80941Smrg{ 87b8e80941Smrg return group->opcode; 88b8e80941Smrg} 89b8e80941Smrg 90b8e80941Smrgstruct v3d_group * 91b8e80941Smrgv3d_spec_find_struct(struct v3d_spec *spec, const char *name) 92b8e80941Smrg{ 93b8e80941Smrg for (int i = 0; i < spec->nstructs; i++) 94b8e80941Smrg if (strcmp(spec->structs[i]->name, name) == 0) 95b8e80941Smrg return spec->structs[i]; 96b8e80941Smrg 97b8e80941Smrg return NULL; 98b8e80941Smrg} 99b8e80941Smrg 100b8e80941Smrgstruct v3d_group * 101b8e80941Smrgv3d_spec_find_register(struct v3d_spec *spec, uint32_t offset) 102b8e80941Smrg{ 103b8e80941Smrg for (int i = 0; i < spec->nregisters; i++) 104b8e80941Smrg if (spec->registers[i]->register_offset == offset) 105b8e80941Smrg return spec->registers[i]; 106b8e80941Smrg 107b8e80941Smrg return NULL; 108b8e80941Smrg} 109b8e80941Smrg 110b8e80941Smrgstruct v3d_group * 111b8e80941Smrgv3d_spec_find_register_by_name(struct v3d_spec *spec, const char *name) 112b8e80941Smrg{ 113b8e80941Smrg for (int i = 0; i < spec->nregisters; i++) { 114b8e80941Smrg if (strcmp(spec->registers[i]->name, name) == 0) 115b8e80941Smrg return spec->registers[i]; 116b8e80941Smrg } 117b8e80941Smrg 118b8e80941Smrg return NULL; 119b8e80941Smrg} 120b8e80941Smrg 121b8e80941Smrgstruct v3d_enum * 122b8e80941Smrgv3d_spec_find_enum(struct v3d_spec *spec, const char *name) 123b8e80941Smrg{ 124b8e80941Smrg for (int i = 0; i < spec->nenums; i++) 125b8e80941Smrg if (strcmp(spec->enums[i]->name, name) == 0) 126b8e80941Smrg return spec->enums[i]; 127b8e80941Smrg 128b8e80941Smrg return NULL; 129b8e80941Smrg} 130b8e80941Smrg 131b8e80941Smrgstatic void __attribute__((noreturn)) 132b8e80941Smrgfail(struct location *loc, const char *msg, ...) 133b8e80941Smrg{ 134b8e80941Smrg va_list ap; 135b8e80941Smrg 136b8e80941Smrg va_start(ap, msg); 137b8e80941Smrg fprintf(stderr, "%s:%d: error: ", 138b8e80941Smrg loc->filename, loc->line_number); 139b8e80941Smrg vfprintf(stderr, msg, ap); 140b8e80941Smrg fprintf(stderr, "\n"); 141b8e80941Smrg va_end(ap); 142b8e80941Smrg exit(EXIT_FAILURE); 143b8e80941Smrg} 144b8e80941Smrg 145b8e80941Smrgstatic void * 146b8e80941Smrgfail_on_null(void *p) 147b8e80941Smrg{ 148b8e80941Smrg if (p == NULL) { 149b8e80941Smrg fprintf(stderr, "aubinator: out of memory\n"); 150b8e80941Smrg exit(EXIT_FAILURE); 151b8e80941Smrg } 152b8e80941Smrg 153b8e80941Smrg return p; 154b8e80941Smrg} 155b8e80941Smrg 156b8e80941Smrgstatic char * 157b8e80941Smrgxstrdup(const char *s) 158b8e80941Smrg{ 159b8e80941Smrg return fail_on_null(strdup(s)); 160b8e80941Smrg} 161b8e80941Smrg 162b8e80941Smrgstatic void * 163b8e80941Smrgzalloc(size_t s) 164b8e80941Smrg{ 165b8e80941Smrg return calloc(s, 1); 166b8e80941Smrg} 167b8e80941Smrg 168b8e80941Smrgstatic void * 169b8e80941Smrgxzalloc(size_t s) 170b8e80941Smrg{ 171b8e80941Smrg return fail_on_null(zalloc(s)); 172b8e80941Smrg} 173b8e80941Smrg 174b8e80941Smrg/* We allow fields to have either a bit index, or append "b" for a byte index. 175b8e80941Smrg */ 176b8e80941Smrgstatic bool 177b8e80941Smrgis_byte_offset(const char *value) 178b8e80941Smrg{ 179b8e80941Smrg return value[strlen(value) - 1] == 'b'; 180b8e80941Smrg} 181b8e80941Smrg 182b8e80941Smrgstatic void 183b8e80941Smrgget_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count, 184b8e80941Smrg uint32_t *size, bool *variable) 185b8e80941Smrg{ 186b8e80941Smrg char *p; 187b8e80941Smrg int i; 188b8e80941Smrg 189b8e80941Smrg for (i = 0; atts[i]; i += 2) { 190b8e80941Smrg if (strcmp(atts[i], "count") == 0) { 191b8e80941Smrg *count = strtoul(atts[i + 1], &p, 0); 192b8e80941Smrg if (*count == 0) 193b8e80941Smrg *variable = true; 194b8e80941Smrg } else if (strcmp(atts[i], "start") == 0) { 195b8e80941Smrg *offset = strtoul(atts[i + 1], &p, 0); 196b8e80941Smrg } else if (strcmp(atts[i], "size") == 0) { 197b8e80941Smrg *size = strtoul(atts[i + 1], &p, 0); 198b8e80941Smrg } 199b8e80941Smrg } 200b8e80941Smrg return; 201b8e80941Smrg} 202b8e80941Smrg 203b8e80941Smrgstatic struct v3d_group * 204b8e80941Smrgcreate_group(struct parser_context *ctx, 205b8e80941Smrg const char *name, 206b8e80941Smrg const char **atts, 207b8e80941Smrg struct v3d_group *parent) 208b8e80941Smrg{ 209b8e80941Smrg struct v3d_group *group; 210b8e80941Smrg 211b8e80941Smrg group = xzalloc(sizeof(*group)); 212b8e80941Smrg if (name) 213b8e80941Smrg group->name = xstrdup(name); 214b8e80941Smrg 215b8e80941Smrg group->spec = ctx->spec; 216b8e80941Smrg group->group_offset = 0; 217b8e80941Smrg group->group_count = 0; 218b8e80941Smrg group->variable = false; 219b8e80941Smrg 220b8e80941Smrg if (parent) { 221b8e80941Smrg group->parent = parent; 222b8e80941Smrg get_group_offset_count(atts, 223b8e80941Smrg &group->group_offset, 224b8e80941Smrg &group->group_count, 225b8e80941Smrg &group->group_size, 226b8e80941Smrg &group->variable); 227b8e80941Smrg } 228b8e80941Smrg 229b8e80941Smrg return group; 230b8e80941Smrg} 231b8e80941Smrg 232b8e80941Smrgstatic struct v3d_enum * 233b8e80941Smrgcreate_enum(struct parser_context *ctx, const char *name, const char **atts) 234b8e80941Smrg{ 235b8e80941Smrg struct v3d_enum *e; 236b8e80941Smrg 237b8e80941Smrg e = xzalloc(sizeof(*e)); 238b8e80941Smrg if (name) 239b8e80941Smrg e->name = xstrdup(name); 240b8e80941Smrg 241b8e80941Smrg e->nvalues = 0; 242b8e80941Smrg 243b8e80941Smrg return e; 244b8e80941Smrg} 245b8e80941Smrg 246b8e80941Smrgstatic void 247b8e80941Smrgget_register_offset(const char **atts, uint32_t *offset) 248b8e80941Smrg{ 249b8e80941Smrg char *p; 250b8e80941Smrg int i; 251b8e80941Smrg 252b8e80941Smrg for (i = 0; atts[i]; i += 2) { 253b8e80941Smrg if (strcmp(atts[i], "num") == 0) 254b8e80941Smrg *offset = strtoul(atts[i + 1], &p, 0); 255b8e80941Smrg } 256b8e80941Smrg return; 257b8e80941Smrg} 258b8e80941Smrg 259b8e80941Smrgstatic void 260b8e80941Smrgget_start_end_pos(int *start, int *end) 261b8e80941Smrg{ 262b8e80941Smrg /* start value has to be mod with 32 as we need the relative 263b8e80941Smrg * start position in the first DWord. For the end position, add 264b8e80941Smrg * the length of the field to the start position to get the 265b8e80941Smrg * relative postion in the 64 bit address. 266b8e80941Smrg */ 267b8e80941Smrg if (*end - *start > 32) { 268b8e80941Smrg int len = *end - *start; 269b8e80941Smrg *start = *start % 32; 270b8e80941Smrg *end = *start + len; 271b8e80941Smrg } else { 272b8e80941Smrg *start = *start % 32; 273b8e80941Smrg *end = *end % 32; 274b8e80941Smrg } 275b8e80941Smrg 276b8e80941Smrg return; 277b8e80941Smrg} 278b8e80941Smrg 279b8e80941Smrgstatic inline uint64_t 280b8e80941Smrgmask(int start, int end) 281b8e80941Smrg{ 282b8e80941Smrg uint64_t v; 283b8e80941Smrg 284b8e80941Smrg v = ~0ULL >> (63 - end + start); 285b8e80941Smrg 286b8e80941Smrg return v << start; 287b8e80941Smrg} 288b8e80941Smrg 289b8e80941Smrgstatic inline uint64_t 290b8e80941Smrgfield(uint64_t value, int start, int end) 291b8e80941Smrg{ 292b8e80941Smrg get_start_end_pos(&start, &end); 293b8e80941Smrg return (value & mask(start, end)) >> (start); 294b8e80941Smrg} 295b8e80941Smrg 296b8e80941Smrgstatic inline uint64_t 297b8e80941Smrgfield_address(uint64_t value, int start, int end) 298b8e80941Smrg{ 299b8e80941Smrg /* no need to right shift for address/offset */ 300b8e80941Smrg get_start_end_pos(&start, &end); 301b8e80941Smrg return (value & mask(start, end)); 302b8e80941Smrg} 303b8e80941Smrg 304b8e80941Smrgstatic struct v3d_type 305b8e80941Smrgstring_to_type(struct parser_context *ctx, const char *s) 306b8e80941Smrg{ 307b8e80941Smrg int i, f; 308b8e80941Smrg struct v3d_group *g; 309b8e80941Smrg struct v3d_enum *e; 310b8e80941Smrg 311b8e80941Smrg if (strcmp(s, "int") == 0) 312b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_INT }; 313b8e80941Smrg else if (strcmp(s, "uint") == 0) 314b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_UINT }; 315b8e80941Smrg else if (strcmp(s, "bool") == 0) 316b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_BOOL }; 317b8e80941Smrg else if (strcmp(s, "float") == 0) 318b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_FLOAT }; 319b8e80941Smrg else if (strcmp(s, "f187") == 0) 320b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_F187 }; 321b8e80941Smrg else if (strcmp(s, "address") == 0) 322b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_ADDRESS }; 323b8e80941Smrg else if (strcmp(s, "offset") == 0) 324b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_OFFSET }; 325b8e80941Smrg else if (sscanf(s, "u%d.%d", &i, &f) == 2) 326b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_UFIXED, .i = i, .f = f }; 327b8e80941Smrg else if (sscanf(s, "s%d.%d", &i, &f) == 2) 328b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_SFIXED, .i = i, .f = f }; 329b8e80941Smrg else if (g = v3d_spec_find_struct(ctx->spec, s), g != NULL) 330b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_STRUCT, .v3d_struct = g }; 331b8e80941Smrg else if (e = v3d_spec_find_enum(ctx->spec, s), e != NULL) 332b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_ENUM, .v3d_enum = e }; 333b8e80941Smrg else if (strcmp(s, "mbo") == 0) 334b8e80941Smrg return (struct v3d_type) { .kind = V3D_TYPE_MBO }; 335b8e80941Smrg else 336b8e80941Smrg fail(&ctx->loc, "invalid type: %s", s); 337b8e80941Smrg} 338b8e80941Smrg 339b8e80941Smrgstatic struct v3d_field * 340b8e80941Smrgcreate_field(struct parser_context *ctx, const char **atts) 341b8e80941Smrg{ 342b8e80941Smrg struct v3d_field *field; 343b8e80941Smrg char *p; 344b8e80941Smrg int i; 345b8e80941Smrg uint32_t size = 0; 346b8e80941Smrg 347b8e80941Smrg field = xzalloc(sizeof(*field)); 348b8e80941Smrg 349b8e80941Smrg for (i = 0; atts[i]; i += 2) { 350b8e80941Smrg if (strcmp(atts[i], "name") == 0) 351b8e80941Smrg field->name = xstrdup(atts[i + 1]); 352b8e80941Smrg else if (strcmp(atts[i], "start") == 0) { 353b8e80941Smrg field->start = strtoul(atts[i + 1], &p, 0); 354b8e80941Smrg if (is_byte_offset(atts[i + 1])) 355b8e80941Smrg field->start *= 8; 356b8e80941Smrg } else if (strcmp(atts[i], "end") == 0) { 357b8e80941Smrg field->end = strtoul(atts[i + 1], &p, 0) - 1; 358b8e80941Smrg if (is_byte_offset(atts[i + 1])) 359b8e80941Smrg field->end *= 8; 360b8e80941Smrg } else if (strcmp(atts[i], "size") == 0) { 361b8e80941Smrg size = strtoul(atts[i + 1], &p, 0); 362b8e80941Smrg if (is_byte_offset(atts[i + 1])) 363b8e80941Smrg size *= 8; 364b8e80941Smrg } else if (strcmp(atts[i], "type") == 0) 365b8e80941Smrg field->type = string_to_type(ctx, atts[i + 1]); 366b8e80941Smrg else if (strcmp(atts[i], "default") == 0) { 367b8e80941Smrg field->has_default = true; 368b8e80941Smrg field->default_value = strtoul(atts[i + 1], &p, 0); 369b8e80941Smrg } else if (strcmp(atts[i], "minus_one") == 0) { 370b8e80941Smrg assert(strcmp(atts[i + 1], "true") == 0); 371b8e80941Smrg field->minus_one = true; 372b8e80941Smrg } 373b8e80941Smrg } 374b8e80941Smrg 375b8e80941Smrg if (size) 376b8e80941Smrg field->end = field->start + size - 1; 377b8e80941Smrg 378b8e80941Smrg return field; 379b8e80941Smrg} 380b8e80941Smrg 381b8e80941Smrgstatic struct v3d_value * 382b8e80941Smrgcreate_value(struct parser_context *ctx, const char **atts) 383b8e80941Smrg{ 384b8e80941Smrg struct v3d_value *value = xzalloc(sizeof(*value)); 385b8e80941Smrg 386b8e80941Smrg for (int i = 0; atts[i]; i += 2) { 387b8e80941Smrg if (strcmp(atts[i], "name") == 0) 388b8e80941Smrg value->name = xstrdup(atts[i + 1]); 389b8e80941Smrg else if (strcmp(atts[i], "value") == 0) 390b8e80941Smrg value->value = strtoul(atts[i + 1], NULL, 0); 391b8e80941Smrg } 392b8e80941Smrg 393b8e80941Smrg return value; 394b8e80941Smrg} 395b8e80941Smrg 396b8e80941Smrgstatic void 397b8e80941Smrgcreate_and_append_field(struct parser_context *ctx, 398b8e80941Smrg const char **atts) 399b8e80941Smrg{ 400b8e80941Smrg if (ctx->group->nfields == ctx->group->fields_size) { 401b8e80941Smrg ctx->group->fields_size = MAX2(ctx->group->fields_size * 2, 2); 402b8e80941Smrg ctx->group->fields = 403b8e80941Smrg (struct v3d_field **) realloc(ctx->group->fields, 404b8e80941Smrg sizeof(ctx->group->fields[0]) * 405b8e80941Smrg ctx->group->fields_size); 406b8e80941Smrg } 407b8e80941Smrg 408b8e80941Smrg ctx->group->fields[ctx->group->nfields++] = create_field(ctx, atts); 409b8e80941Smrg} 410b8e80941Smrg 411b8e80941Smrgstatic void 412b8e80941Smrgset_group_opcode(struct v3d_group *group, const char **atts) 413b8e80941Smrg{ 414b8e80941Smrg char *p; 415b8e80941Smrg int i; 416b8e80941Smrg 417b8e80941Smrg for (i = 0; atts[i]; i += 2) { 418b8e80941Smrg if (strcmp(atts[i], "code") == 0) 419b8e80941Smrg group->opcode = strtoul(atts[i + 1], &p, 0); 420b8e80941Smrg } 421b8e80941Smrg return; 422b8e80941Smrg} 423b8e80941Smrg 424b8e80941Smrgstatic bool 425b8e80941Smrgver_in_range(int ver, int min_ver, int max_ver) 426b8e80941Smrg{ 427b8e80941Smrg return ((min_ver == 0 || ver >= min_ver) && 428b8e80941Smrg (max_ver == 0 || ver <= max_ver)); 429b8e80941Smrg} 430b8e80941Smrg 431b8e80941Smrgstatic bool 432b8e80941Smrgskip_if_ver_mismatch(struct parser_context *ctx, int min_ver, int max_ver) 433b8e80941Smrg{ 434b8e80941Smrg if (!ctx->parse_skip_depth && !ver_in_range(ctx->devinfo->ver, 435b8e80941Smrg min_ver, max_ver)) { 436b8e80941Smrg assert(ctx->parse_depth != 0); 437b8e80941Smrg ctx->parse_skip_depth = ctx->parse_depth; 438b8e80941Smrg } 439b8e80941Smrg 440b8e80941Smrg return ctx->parse_skip_depth; 441b8e80941Smrg} 442b8e80941Smrg 443b8e80941Smrgstatic void 444b8e80941Smrgstart_element(void *data, const char *element_name, const char **atts) 445b8e80941Smrg{ 446b8e80941Smrg struct parser_context *ctx = data; 447b8e80941Smrg int i; 448b8e80941Smrg const char *name = NULL; 449b8e80941Smrg const char *ver = NULL; 450b8e80941Smrg int min_ver = 0; 451b8e80941Smrg int max_ver = 0; 452b8e80941Smrg 453b8e80941Smrg ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); 454b8e80941Smrg 455b8e80941Smrg for (i = 0; atts[i]; i += 2) { 456b8e80941Smrg if (strcmp(atts[i], "shortname") == 0) 457b8e80941Smrg name = atts[i + 1]; 458b8e80941Smrg else if (strcmp(atts[i], "name") == 0 && !name) 459b8e80941Smrg name = atts[i + 1]; 460b8e80941Smrg else if (strcmp(atts[i], "gen") == 0) 461b8e80941Smrg ver = atts[i + 1]; 462b8e80941Smrg else if (strcmp(atts[i], "min_ver") == 0) 463b8e80941Smrg min_ver = strtoul(atts[i + 1], NULL, 0); 464b8e80941Smrg else if (strcmp(atts[i], "max_ver") == 0) 465b8e80941Smrg max_ver = strtoul(atts[i + 1], NULL, 0); 466b8e80941Smrg } 467b8e80941Smrg 468b8e80941Smrg if (skip_if_ver_mismatch(ctx, min_ver, max_ver)) 469b8e80941Smrg goto skip; 470b8e80941Smrg 471b8e80941Smrg if (strcmp(element_name, "vcxml") == 0) { 472b8e80941Smrg if (ver == NULL) 473b8e80941Smrg fail(&ctx->loc, "no ver given"); 474b8e80941Smrg 475b8e80941Smrg /* Make sure that we picked an XML that matched our version. 476b8e80941Smrg */ 477b8e80941Smrg assert(ver_in_range(ctx->devinfo->ver, min_ver, max_ver)); 478b8e80941Smrg 479b8e80941Smrg int major, minor; 480b8e80941Smrg int n = sscanf(ver, "%d.%d", &major, &minor); 481b8e80941Smrg if (n == 0) 482b8e80941Smrg fail(&ctx->loc, "invalid ver given: %s", ver); 483b8e80941Smrg if (n == 1) 484b8e80941Smrg minor = 0; 485b8e80941Smrg 486b8e80941Smrg ctx->spec->ver = major * 10 + minor; 487b8e80941Smrg } else if (strcmp(element_name, "packet") == 0 || 488b8e80941Smrg strcmp(element_name, "struct") == 0) { 489b8e80941Smrg ctx->group = create_group(ctx, name, atts, NULL); 490b8e80941Smrg 491b8e80941Smrg if (strcmp(element_name, "packet") == 0) 492b8e80941Smrg set_group_opcode(ctx->group, atts); 493b8e80941Smrg } else if (strcmp(element_name, "register") == 0) { 494b8e80941Smrg ctx->group = create_group(ctx, name, atts, NULL); 495b8e80941Smrg get_register_offset(atts, &ctx->group->register_offset); 496b8e80941Smrg } else if (strcmp(element_name, "group") == 0) { 497b8e80941Smrg struct v3d_group *previous_group = ctx->group; 498b8e80941Smrg while (previous_group->next) 499b8e80941Smrg previous_group = previous_group->next; 500b8e80941Smrg 501b8e80941Smrg struct v3d_group *group = create_group(ctx, "", atts, 502b8e80941Smrg ctx->group); 503b8e80941Smrg previous_group->next = group; 504b8e80941Smrg ctx->group = group; 505b8e80941Smrg } else if (strcmp(element_name, "field") == 0) { 506b8e80941Smrg create_and_append_field(ctx, atts); 507b8e80941Smrg } else if (strcmp(element_name, "enum") == 0) { 508b8e80941Smrg ctx->enoom = create_enum(ctx, name, atts); 509b8e80941Smrg } else if (strcmp(element_name, "value") == 0) { 510b8e80941Smrg ctx->values[ctx->nvalues++] = create_value(ctx, atts); 511b8e80941Smrg assert(ctx->nvalues < ARRAY_SIZE(ctx->values)); 512b8e80941Smrg } 513b8e80941Smrg 514b8e80941Smrgskip: 515b8e80941Smrg ctx->parse_depth++; 516b8e80941Smrg} 517b8e80941Smrg 518b8e80941Smrgstatic int 519b8e80941Smrgfield_offset_compare(const void *a, const void *b) 520b8e80941Smrg{ 521b8e80941Smrg return ((*(const struct v3d_field **)a)->start - 522b8e80941Smrg (*(const struct v3d_field **)b)->start); 523b8e80941Smrg} 524b8e80941Smrg 525b8e80941Smrgstatic void 526b8e80941Smrgend_element(void *data, const char *name) 527b8e80941Smrg{ 528b8e80941Smrg struct parser_context *ctx = data; 529b8e80941Smrg struct v3d_spec *spec = ctx->spec; 530b8e80941Smrg 531b8e80941Smrg ctx->parse_depth--; 532b8e80941Smrg 533b8e80941Smrg if (ctx->parse_skip_depth) { 534b8e80941Smrg if (ctx->parse_skip_depth == ctx->parse_depth) 535b8e80941Smrg ctx->parse_skip_depth = 0; 536b8e80941Smrg return; 537b8e80941Smrg } 538b8e80941Smrg 539b8e80941Smrg if (strcmp(name, "packet") == 0 || 540b8e80941Smrg strcmp(name, "struct") == 0 || 541b8e80941Smrg strcmp(name, "register") == 0) { 542b8e80941Smrg struct v3d_group *group = ctx->group; 543b8e80941Smrg 544b8e80941Smrg ctx->group = ctx->group->parent; 545b8e80941Smrg 546b8e80941Smrg if (strcmp(name, "packet") == 0) { 547b8e80941Smrg spec->commands[spec->ncommands++] = group; 548b8e80941Smrg 549b8e80941Smrg /* V3D packet XML has the packet contents with offsets 550b8e80941Smrg * starting from the first bit after the opcode, to 551b8e80941Smrg * match the spec. Shift the fields up now. 552b8e80941Smrg */ 553b8e80941Smrg for (int i = 0; i < group->nfields; i++) { 554b8e80941Smrg group->fields[i]->start += 8; 555b8e80941Smrg group->fields[i]->end += 8; 556b8e80941Smrg } 557b8e80941Smrg } 558b8e80941Smrg else if (strcmp(name, "struct") == 0) 559b8e80941Smrg spec->structs[spec->nstructs++] = group; 560b8e80941Smrg else if (strcmp(name, "register") == 0) 561b8e80941Smrg spec->registers[spec->nregisters++] = group; 562b8e80941Smrg 563b8e80941Smrg /* Sort the fields in increasing offset order. The XML might 564b8e80941Smrg * be specified in any order, but we'll want to iterate from 565b8e80941Smrg * the bottom. 566b8e80941Smrg */ 567b8e80941Smrg qsort(group->fields, group->nfields, sizeof(*group->fields), 568b8e80941Smrg field_offset_compare); 569b8e80941Smrg 570b8e80941Smrg assert(spec->ncommands < ARRAY_SIZE(spec->commands)); 571b8e80941Smrg assert(spec->nstructs < ARRAY_SIZE(spec->structs)); 572b8e80941Smrg assert(spec->nregisters < ARRAY_SIZE(spec->registers)); 573b8e80941Smrg } else if (strcmp(name, "group") == 0) { 574b8e80941Smrg ctx->group = ctx->group->parent; 575b8e80941Smrg } else if (strcmp(name, "field") == 0) { 576b8e80941Smrg assert(ctx->group->nfields > 0); 577b8e80941Smrg struct v3d_field *field = ctx->group->fields[ctx->group->nfields - 1]; 578b8e80941Smrg size_t size = ctx->nvalues * sizeof(ctx->values[0]); 579b8e80941Smrg field->inline_enum.values = xzalloc(size); 580b8e80941Smrg field->inline_enum.nvalues = ctx->nvalues; 581b8e80941Smrg memcpy(field->inline_enum.values, ctx->values, size); 582b8e80941Smrg ctx->nvalues = 0; 583b8e80941Smrg } else if (strcmp(name, "enum") == 0) { 584b8e80941Smrg struct v3d_enum *e = ctx->enoom; 585b8e80941Smrg size_t size = ctx->nvalues * sizeof(ctx->values[0]); 586b8e80941Smrg e->values = xzalloc(size); 587b8e80941Smrg e->nvalues = ctx->nvalues; 588b8e80941Smrg memcpy(e->values, ctx->values, size); 589b8e80941Smrg ctx->nvalues = 0; 590b8e80941Smrg ctx->enoom = NULL; 591b8e80941Smrg spec->enums[spec->nenums++] = e; 592b8e80941Smrg } 593b8e80941Smrg} 594b8e80941Smrg 595b8e80941Smrgstatic void 596b8e80941Smrgcharacter_data(void *data, const XML_Char *s, int len) 597b8e80941Smrg{ 598b8e80941Smrg} 599b8e80941Smrg 600b8e80941Smrgstatic uint32_t zlib_inflate(const void *compressed_data, 601b8e80941Smrg uint32_t compressed_len, 602b8e80941Smrg void **out_ptr) 603b8e80941Smrg{ 604b8e80941Smrg struct z_stream_s zstream; 605b8e80941Smrg void *out; 606b8e80941Smrg 607b8e80941Smrg memset(&zstream, 0, sizeof(zstream)); 608b8e80941Smrg 609b8e80941Smrg zstream.next_in = (unsigned char *)compressed_data; 610b8e80941Smrg zstream.avail_in = compressed_len; 611b8e80941Smrg 612b8e80941Smrg if (inflateInit(&zstream) != Z_OK) 613b8e80941Smrg return 0; 614b8e80941Smrg 615b8e80941Smrg out = malloc(4096); 616b8e80941Smrg zstream.next_out = out; 617b8e80941Smrg zstream.avail_out = 4096; 618b8e80941Smrg 619b8e80941Smrg do { 620b8e80941Smrg switch (inflate(&zstream, Z_SYNC_FLUSH)) { 621b8e80941Smrg case Z_STREAM_END: 622b8e80941Smrg goto end; 623b8e80941Smrg case Z_OK: 624b8e80941Smrg break; 625b8e80941Smrg default: 626b8e80941Smrg inflateEnd(&zstream); 627b8e80941Smrg return 0; 628b8e80941Smrg } 629b8e80941Smrg 630b8e80941Smrg if (zstream.avail_out) 631b8e80941Smrg break; 632b8e80941Smrg 633b8e80941Smrg out = realloc(out, 2*zstream.total_out); 634b8e80941Smrg if (out == NULL) { 635b8e80941Smrg inflateEnd(&zstream); 636b8e80941Smrg return 0; 637b8e80941Smrg } 638b8e80941Smrg 639b8e80941Smrg zstream.next_out = (unsigned char *)out + zstream.total_out; 640b8e80941Smrg zstream.avail_out = zstream.total_out; 641b8e80941Smrg } while (1); 642b8e80941Smrg end: 643b8e80941Smrg inflateEnd(&zstream); 644b8e80941Smrg *out_ptr = out; 645b8e80941Smrg return zstream.total_out; 646b8e80941Smrg} 647b8e80941Smrg 648b8e80941Smrgstruct v3d_spec * 649b8e80941Smrgv3d_spec_load(const struct v3d_device_info *devinfo) 650b8e80941Smrg{ 651b8e80941Smrg struct parser_context ctx; 652b8e80941Smrg void *buf; 653b8e80941Smrg uint8_t *text_data = NULL; 654b8e80941Smrg uint32_t text_offset = 0, text_length = 0; 655b8e80941Smrg MAYBE_UNUSED uint32_t total_length; 656b8e80941Smrg 657b8e80941Smrg for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) { 658b8e80941Smrg if (i != 0) { 659b8e80941Smrg assert(genxml_files_table[i - 1].gen_10 < 660b8e80941Smrg genxml_files_table[i].gen_10); 661b8e80941Smrg } 662b8e80941Smrg 663b8e80941Smrg if (genxml_files_table[i].gen_10 <= devinfo->ver) { 664b8e80941Smrg text_offset = genxml_files_table[i].offset; 665b8e80941Smrg text_length = genxml_files_table[i].length; 666b8e80941Smrg } 667b8e80941Smrg } 668b8e80941Smrg 669b8e80941Smrg if (text_length == 0) { 670b8e80941Smrg fprintf(stderr, "unable to find gen (%u) data\n", devinfo->ver); 671b8e80941Smrg return NULL; 672b8e80941Smrg } 673b8e80941Smrg 674b8e80941Smrg memset(&ctx, 0, sizeof ctx); 675b8e80941Smrg ctx.parser = XML_ParserCreate(NULL); 676b8e80941Smrg ctx.devinfo = devinfo; 677b8e80941Smrg XML_SetUserData(ctx.parser, &ctx); 678b8e80941Smrg if (ctx.parser == NULL) { 679b8e80941Smrg fprintf(stderr, "failed to create parser\n"); 680b8e80941Smrg return NULL; 681b8e80941Smrg } 682b8e80941Smrg 683b8e80941Smrg XML_SetElementHandler(ctx.parser, start_element, end_element); 684b8e80941Smrg XML_SetCharacterDataHandler(ctx.parser, character_data); 685b8e80941Smrg 686b8e80941Smrg ctx.spec = xzalloc(sizeof(*ctx.spec)); 687b8e80941Smrg 688b8e80941Smrg total_length = zlib_inflate(compress_genxmls, 689b8e80941Smrg sizeof(compress_genxmls), 690b8e80941Smrg (void **) &text_data); 691b8e80941Smrg assert(text_offset + text_length <= total_length); 692b8e80941Smrg 693b8e80941Smrg buf = XML_GetBuffer(ctx.parser, text_length); 694b8e80941Smrg memcpy(buf, &text_data[text_offset], text_length); 695b8e80941Smrg 696b8e80941Smrg if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) { 697b8e80941Smrg fprintf(stderr, 698b8e80941Smrg "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n", 699b8e80941Smrg XML_GetCurrentLineNumber(ctx.parser), 700b8e80941Smrg XML_GetCurrentColumnNumber(ctx.parser), 701b8e80941Smrg XML_GetCurrentByteIndex(ctx.parser), text_length, 702b8e80941Smrg XML_ErrorString(XML_GetErrorCode(ctx.parser))); 703b8e80941Smrg XML_ParserFree(ctx.parser); 704b8e80941Smrg free(text_data); 705b8e80941Smrg return NULL; 706b8e80941Smrg } 707b8e80941Smrg 708b8e80941Smrg XML_ParserFree(ctx.parser); 709b8e80941Smrg free(text_data); 710b8e80941Smrg 711b8e80941Smrg return ctx.spec; 712b8e80941Smrg} 713b8e80941Smrg 714b8e80941Smrgstruct v3d_group * 715b8e80941Smrgv3d_spec_find_instruction(struct v3d_spec *spec, const uint8_t *p) 716b8e80941Smrg{ 717b8e80941Smrg uint8_t opcode = *p; 718b8e80941Smrg 719b8e80941Smrg for (int i = 0; i < spec->ncommands; i++) { 720b8e80941Smrg struct v3d_group *group = spec->commands[i]; 721b8e80941Smrg 722b8e80941Smrg if (opcode != group->opcode) 723b8e80941Smrg continue; 724b8e80941Smrg 725b8e80941Smrg /* If there's a "sub-id" field, make sure that it matches the 726b8e80941Smrg * instruction being decoded. 727b8e80941Smrg */ 728b8e80941Smrg struct v3d_field *subid = NULL; 729b8e80941Smrg for (int j = 0; j < group->nfields; j++) { 730b8e80941Smrg struct v3d_field *field = group->fields[j]; 731b8e80941Smrg if (strcmp(field->name, "sub-id") == 0) { 732b8e80941Smrg subid = field; 733b8e80941Smrg break; 734b8e80941Smrg } 735b8e80941Smrg } 736b8e80941Smrg 737b8e80941Smrg if (subid && (__gen_unpack_uint(p, subid->start, subid->end) != 738b8e80941Smrg subid->default_value)) { 739b8e80941Smrg continue; 740b8e80941Smrg } 741b8e80941Smrg 742b8e80941Smrg return group; 743b8e80941Smrg } 744b8e80941Smrg 745b8e80941Smrg return NULL; 746b8e80941Smrg} 747b8e80941Smrg 748b8e80941Smrg/** Returns the size of a V3D packet. */ 749b8e80941Smrgint 750b8e80941Smrgv3d_group_get_length(struct v3d_group *group) 751b8e80941Smrg{ 752b8e80941Smrg int last_bit = 0; 753b8e80941Smrg for (int i = 0; i < group->nfields; i++) { 754b8e80941Smrg struct v3d_field *field = group->fields[i]; 755b8e80941Smrg 756b8e80941Smrg last_bit = MAX2(last_bit, field->end); 757b8e80941Smrg } 758b8e80941Smrg return last_bit / 8 + 1; 759b8e80941Smrg} 760b8e80941Smrg 761b8e80941Smrgvoid 762b8e80941Smrgv3d_field_iterator_init(struct v3d_field_iterator *iter, 763b8e80941Smrg struct v3d_group *group, 764b8e80941Smrg const uint8_t *p) 765b8e80941Smrg{ 766b8e80941Smrg memset(iter, 0, sizeof(*iter)); 767b8e80941Smrg 768b8e80941Smrg iter->group = group; 769b8e80941Smrg iter->p = p; 770b8e80941Smrg} 771b8e80941Smrg 772b8e80941Smrgstatic const char * 773b8e80941Smrgv3d_get_enum_name(struct v3d_enum *e, uint64_t value) 774b8e80941Smrg{ 775b8e80941Smrg for (int i = 0; i < e->nvalues; i++) { 776b8e80941Smrg if (e->values[i]->value == value) { 777b8e80941Smrg return e->values[i]->name; 778b8e80941Smrg } 779b8e80941Smrg } 780b8e80941Smrg return NULL; 781b8e80941Smrg} 782b8e80941Smrg 783b8e80941Smrgstatic bool 784b8e80941Smrgiter_more_fields(const struct v3d_field_iterator *iter) 785b8e80941Smrg{ 786b8e80941Smrg return iter->field_iter < iter->group->nfields; 787b8e80941Smrg} 788b8e80941Smrg 789b8e80941Smrgstatic uint32_t 790b8e80941Smrgiter_group_offset_bits(const struct v3d_field_iterator *iter, 791b8e80941Smrg uint32_t group_iter) 792b8e80941Smrg{ 793b8e80941Smrg return iter->group->group_offset + (group_iter * 794b8e80941Smrg iter->group->group_size); 795b8e80941Smrg} 796b8e80941Smrg 797b8e80941Smrgstatic bool 798b8e80941Smrgiter_more_groups(const struct v3d_field_iterator *iter) 799b8e80941Smrg{ 800b8e80941Smrg if (iter->group->variable) { 801b8e80941Smrg return iter_group_offset_bits(iter, iter->group_iter + 1) < 802b8e80941Smrg (v3d_group_get_length(iter->group) * 8); 803b8e80941Smrg } else { 804b8e80941Smrg return (iter->group_iter + 1) < iter->group->group_count || 805b8e80941Smrg iter->group->next != NULL; 806b8e80941Smrg } 807b8e80941Smrg} 808b8e80941Smrg 809b8e80941Smrgstatic void 810b8e80941Smrgiter_advance_group(struct v3d_field_iterator *iter) 811b8e80941Smrg{ 812b8e80941Smrg if (iter->group->variable) 813b8e80941Smrg iter->group_iter++; 814b8e80941Smrg else { 815b8e80941Smrg if ((iter->group_iter + 1) < iter->group->group_count) { 816b8e80941Smrg iter->group_iter++; 817b8e80941Smrg } else { 818b8e80941Smrg iter->group = iter->group->next; 819b8e80941Smrg iter->group_iter = 0; 820b8e80941Smrg } 821b8e80941Smrg } 822b8e80941Smrg 823b8e80941Smrg iter->field_iter = 0; 824b8e80941Smrg} 825b8e80941Smrg 826b8e80941Smrgstatic bool 827b8e80941Smrgiter_advance_field(struct v3d_field_iterator *iter) 828b8e80941Smrg{ 829b8e80941Smrg while (!iter_more_fields(iter)) { 830b8e80941Smrg if (!iter_more_groups(iter)) 831b8e80941Smrg return false; 832b8e80941Smrg 833b8e80941Smrg iter_advance_group(iter); 834b8e80941Smrg } 835b8e80941Smrg 836b8e80941Smrg iter->field = iter->group->fields[iter->field_iter++]; 837b8e80941Smrg if (iter->field->name) 838b8e80941Smrg snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name); 839b8e80941Smrg else 840b8e80941Smrg memset(iter->name, 0, sizeof(iter->name)); 841b8e80941Smrg iter->offset = iter_group_offset_bits(iter, iter->group_iter) / 8 + 842b8e80941Smrg iter->field->start / 8; 843b8e80941Smrg iter->struct_desc = NULL; 844b8e80941Smrg 845b8e80941Smrg return true; 846b8e80941Smrg} 847b8e80941Smrg 848b8e80941Smrgbool 849b8e80941Smrgv3d_field_iterator_next(struct clif_dump *clif, struct v3d_field_iterator *iter) 850b8e80941Smrg{ 851b8e80941Smrg if (!iter_advance_field(iter)) 852b8e80941Smrg return false; 853b8e80941Smrg 854b8e80941Smrg const char *enum_name = NULL; 855b8e80941Smrg 856b8e80941Smrg int group_member_offset = 857b8e80941Smrg iter_group_offset_bits(iter, iter->group_iter); 858b8e80941Smrg int s = group_member_offset + iter->field->start; 859b8e80941Smrg int e = group_member_offset + iter->field->end; 860b8e80941Smrg 861b8e80941Smrg assert(!iter->field->minus_one || 862b8e80941Smrg iter->field->type.kind == V3D_TYPE_INT || 863b8e80941Smrg iter->field->type.kind == V3D_TYPE_UINT); 864b8e80941Smrg 865b8e80941Smrg switch (iter->field->type.kind) { 866b8e80941Smrg case V3D_TYPE_UNKNOWN: 867b8e80941Smrg case V3D_TYPE_INT: { 868b8e80941Smrg uint32_t value = __gen_unpack_sint(iter->p, s, e); 869b8e80941Smrg if (iter->field->minus_one) 870b8e80941Smrg value++; 871b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%d", value); 872b8e80941Smrg enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); 873b8e80941Smrg break; 874b8e80941Smrg } 875b8e80941Smrg case V3D_TYPE_UINT: { 876b8e80941Smrg uint32_t value = __gen_unpack_uint(iter->p, s, e); 877b8e80941Smrg if (iter->field->minus_one) 878b8e80941Smrg value++; 879b8e80941Smrg if (strcmp(iter->field->name, "Vec size") == 0 && value == 0) 880b8e80941Smrg value = 1 << (e - s); 881b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%u", value); 882b8e80941Smrg enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); 883b8e80941Smrg break; 884b8e80941Smrg } 885b8e80941Smrg case V3D_TYPE_BOOL: 886b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%s", 887b8e80941Smrg __gen_unpack_uint(iter->p, s, e) ? 888b8e80941Smrg "1 /* true */" : "0 /* false */"); 889b8e80941Smrg break; 890b8e80941Smrg case V3D_TYPE_FLOAT: 891b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%f", 892b8e80941Smrg __gen_unpack_float(iter->p, s, e)); 893b8e80941Smrg break; 894b8e80941Smrg 895b8e80941Smrg case V3D_TYPE_F187: 896b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%f", 897b8e80941Smrg __gen_unpack_f187(iter->p, s, e)); 898b8e80941Smrg break; 899b8e80941Smrg 900b8e80941Smrg case V3D_TYPE_ADDRESS: { 901b8e80941Smrg uint32_t addr = 902b8e80941Smrg __gen_unpack_uint(iter->p, s, e) << (31 - (e - s)); 903b8e80941Smrg struct clif_bo *bo = clif_lookup_bo(clif, addr); 904b8e80941Smrg if (bo) { 905b8e80941Smrg snprintf(iter->value, sizeof(iter->value), 906b8e80941Smrg "[%s+0x%08x] /* 0x%08x */", 907b8e80941Smrg bo->name, addr - bo->offset, addr); 908b8e80941Smrg } else if (addr) { 909b8e80941Smrg snprintf(iter->value, sizeof(iter->value), 910b8e80941Smrg "/* XXX: BO unknown */ 0x%08x", addr); 911b8e80941Smrg } else { 912b8e80941Smrg snprintf(iter->value, sizeof(iter->value), 913b8e80941Smrg "[null]"); 914b8e80941Smrg } 915b8e80941Smrg 916b8e80941Smrg break; 917b8e80941Smrg } 918b8e80941Smrg 919b8e80941Smrg case V3D_TYPE_OFFSET: 920b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, 921b8e80941Smrg __gen_unpack_uint(iter->p, s, e) << (31 - (e - s))); 922b8e80941Smrg break; 923b8e80941Smrg case V3D_TYPE_STRUCT: 924b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "<struct %s>", 925b8e80941Smrg iter->field->type.v3d_struct->name); 926b8e80941Smrg iter->struct_desc = 927b8e80941Smrg v3d_spec_find_struct(iter->group->spec, 928b8e80941Smrg iter->field->type.v3d_struct->name); 929b8e80941Smrg break; 930b8e80941Smrg case V3D_TYPE_SFIXED: 931b8e80941Smrg if (clif->pretty) { 932b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%f", 933b8e80941Smrg __gen_unpack_sfixed(iter->p, s, e, 934b8e80941Smrg iter->field->type.f)); 935b8e80941Smrg } else { 936b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%u", 937b8e80941Smrg (unsigned)__gen_unpack_uint(iter->p, s, e)); 938b8e80941Smrg } 939b8e80941Smrg break; 940b8e80941Smrg case V3D_TYPE_UFIXED: 941b8e80941Smrg if (clif->pretty) { 942b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%f", 943b8e80941Smrg __gen_unpack_ufixed(iter->p, s, e, 944b8e80941Smrg iter->field->type.f)); 945b8e80941Smrg } else { 946b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%u", 947b8e80941Smrg (unsigned)__gen_unpack_uint(iter->p, s, e)); 948b8e80941Smrg } 949b8e80941Smrg break; 950b8e80941Smrg case V3D_TYPE_MBO: 951b8e80941Smrg break; 952b8e80941Smrg case V3D_TYPE_ENUM: { 953b8e80941Smrg uint32_t value = __gen_unpack_uint(iter->p, s, e); 954b8e80941Smrg snprintf(iter->value, sizeof(iter->value), "%d", value); 955b8e80941Smrg enum_name = v3d_get_enum_name(iter->field->type.v3d_enum, value); 956b8e80941Smrg break; 957b8e80941Smrg } 958b8e80941Smrg } 959b8e80941Smrg 960b8e80941Smrg if (strlen(iter->group->name) == 0) { 961b8e80941Smrg int length = strlen(iter->name); 962b8e80941Smrg snprintf(iter->name + length, sizeof(iter->name) - length, 963b8e80941Smrg "[%i]", iter->group_iter); 964b8e80941Smrg } 965b8e80941Smrg 966b8e80941Smrg if (enum_name) { 967b8e80941Smrg int length = strlen(iter->value); 968b8e80941Smrg snprintf(iter->value + length, sizeof(iter->value) - length, 969b8e80941Smrg " /* %s */", enum_name); 970b8e80941Smrg } 971b8e80941Smrg 972b8e80941Smrg return true; 973b8e80941Smrg} 974b8e80941Smrg 975b8e80941Smrgvoid 976b8e80941Smrgv3d_print_group(struct clif_dump *clif, struct v3d_group *group, 977b8e80941Smrg uint64_t offset, const uint8_t *p) 978b8e80941Smrg{ 979b8e80941Smrg struct v3d_field_iterator iter; 980b8e80941Smrg 981b8e80941Smrg v3d_field_iterator_init(&iter, group, p); 982b8e80941Smrg while (v3d_field_iterator_next(clif, &iter)) { 983b8e80941Smrg /* Clif parsing uses the packet name, and expects no 984b8e80941Smrg * sub-id. 985b8e80941Smrg */ 986b8e80941Smrg if (strcmp(iter.field->name, "sub-id") == 0 || 987b8e80941Smrg strcmp(iter.field->name, "unused") == 0 || 988b8e80941Smrg strcmp(iter.field->name, "Pad") == 0) 989b8e80941Smrg continue; 990b8e80941Smrg 991b8e80941Smrg if (clif->pretty) { 992b8e80941Smrg fprintf(clif->out, " %s: %s\n", 993b8e80941Smrg iter.name, iter.value); 994b8e80941Smrg } else { 995b8e80941Smrg fprintf(clif->out, " /* %30s: */ %s\n", 996b8e80941Smrg iter.name, iter.value); 997b8e80941Smrg } 998b8e80941Smrg if (iter.struct_desc) { 999b8e80941Smrg uint64_t struct_offset = offset + iter.offset; 1000b8e80941Smrg v3d_print_group(clif, iter.struct_desc, 1001b8e80941Smrg struct_offset, 1002b8e80941Smrg &p[iter.offset]); 1003b8e80941Smrg } 1004b8e80941Smrg } 1005b8e80941Smrg} 1006