101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2016 Intel Corporation 301e04c3fSmrg * Copyright © 2017 Broadcom 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 701e04c3fSmrg * to deal in the Software without restriction, including without limitation 801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 1001e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1101e04c3fSmrg * 1201e04c3fSmrg * The above copyright notice and this permission notice (including the next 1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1401e04c3fSmrg * Software. 1501e04c3fSmrg * 1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2101e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2201e04c3fSmrg * IN THE SOFTWARE. 2301e04c3fSmrg */ 2401e04c3fSmrg 257ec681f3Smrg#include "v3d_decoder.h" 267ec681f3Smrg 2701e04c3fSmrg#include <stdio.h> 287ec681f3Smrg#include <stdlib.h> 2901e04c3fSmrg#include <stdbool.h> 3001e04c3fSmrg#include <stdint.h> 3101e04c3fSmrg#include <stdarg.h> 3201e04c3fSmrg#include <string.h> 337ec681f3Smrg#ifdef WITH_LIBEXPAT 3401e04c3fSmrg#include <expat.h> 357ec681f3Smrg#endif 3601e04c3fSmrg#include <inttypes.h> 3701e04c3fSmrg#include <zlib.h> 3801e04c3fSmrg 3901e04c3fSmrg#include <util/macros.h> 4001e04c3fSmrg#include <util/ralloc.h> 417ec681f3Smrg#include <util/u_debug.h> 4201e04c3fSmrg 4301e04c3fSmrg#include "v3d_packet_helpers.h" 4401e04c3fSmrg#include "v3d_xml.h" 4501e04c3fSmrg#include "broadcom/clif/clif_private.h" 4601e04c3fSmrg 4701e04c3fSmrgstruct v3d_spec { 4801e04c3fSmrg uint32_t ver; 4901e04c3fSmrg 5001e04c3fSmrg int ncommands; 5101e04c3fSmrg struct v3d_group *commands[256]; 5201e04c3fSmrg int nstructs; 5301e04c3fSmrg struct v3d_group *structs[256]; 5401e04c3fSmrg int nregisters; 5501e04c3fSmrg struct v3d_group *registers[256]; 5601e04c3fSmrg int nenums; 5701e04c3fSmrg struct v3d_enum *enums[256]; 5801e04c3fSmrg}; 5901e04c3fSmrg 607ec681f3Smrg#ifdef WITH_LIBEXPAT 617ec681f3Smrg 6201e04c3fSmrgstruct location { 6301e04c3fSmrg const char *filename; 6401e04c3fSmrg int line_number; 6501e04c3fSmrg}; 6601e04c3fSmrg 6701e04c3fSmrgstruct parser_context { 6801e04c3fSmrg XML_Parser parser; 6901e04c3fSmrg const struct v3d_device_info *devinfo; 7001e04c3fSmrg int foo; 7101e04c3fSmrg struct location loc; 7201e04c3fSmrg 7301e04c3fSmrg struct v3d_group *group; 7401e04c3fSmrg struct v3d_enum *enoom; 7501e04c3fSmrg 7601e04c3fSmrg int nvalues; 7701e04c3fSmrg struct v3d_value *values[256]; 7801e04c3fSmrg 7901e04c3fSmrg struct v3d_spec *spec; 8001e04c3fSmrg 8101e04c3fSmrg int parse_depth; 8201e04c3fSmrg int parse_skip_depth; 8301e04c3fSmrg}; 8401e04c3fSmrg 857ec681f3Smrg#endif /* WITH_LIBEXPAT */ 867ec681f3Smrg 8701e04c3fSmrgconst char * 8801e04c3fSmrgv3d_group_get_name(struct v3d_group *group) 8901e04c3fSmrg{ 9001e04c3fSmrg return group->name; 9101e04c3fSmrg} 9201e04c3fSmrg 9301e04c3fSmrguint8_t 9401e04c3fSmrgv3d_group_get_opcode(struct v3d_group *group) 9501e04c3fSmrg{ 9601e04c3fSmrg return group->opcode; 9701e04c3fSmrg} 9801e04c3fSmrg 9901e04c3fSmrgstruct v3d_group * 10001e04c3fSmrgv3d_spec_find_struct(struct v3d_spec *spec, const char *name) 10101e04c3fSmrg{ 10201e04c3fSmrg for (int i = 0; i < spec->nstructs; i++) 10301e04c3fSmrg if (strcmp(spec->structs[i]->name, name) == 0) 10401e04c3fSmrg return spec->structs[i]; 10501e04c3fSmrg 10601e04c3fSmrg return NULL; 10701e04c3fSmrg} 10801e04c3fSmrg 10901e04c3fSmrgstruct v3d_group * 11001e04c3fSmrgv3d_spec_find_register(struct v3d_spec *spec, uint32_t offset) 11101e04c3fSmrg{ 11201e04c3fSmrg for (int i = 0; i < spec->nregisters; i++) 11301e04c3fSmrg if (spec->registers[i]->register_offset == offset) 11401e04c3fSmrg return spec->registers[i]; 11501e04c3fSmrg 11601e04c3fSmrg return NULL; 11701e04c3fSmrg} 11801e04c3fSmrg 11901e04c3fSmrgstruct v3d_group * 12001e04c3fSmrgv3d_spec_find_register_by_name(struct v3d_spec *spec, const char *name) 12101e04c3fSmrg{ 12201e04c3fSmrg for (int i = 0; i < spec->nregisters; i++) { 12301e04c3fSmrg if (strcmp(spec->registers[i]->name, name) == 0) 12401e04c3fSmrg return spec->registers[i]; 12501e04c3fSmrg } 12601e04c3fSmrg 12701e04c3fSmrg return NULL; 12801e04c3fSmrg} 12901e04c3fSmrg 13001e04c3fSmrgstruct v3d_enum * 13101e04c3fSmrgv3d_spec_find_enum(struct v3d_spec *spec, const char *name) 13201e04c3fSmrg{ 13301e04c3fSmrg for (int i = 0; i < spec->nenums; i++) 13401e04c3fSmrg if (strcmp(spec->enums[i]->name, name) == 0) 13501e04c3fSmrg return spec->enums[i]; 13601e04c3fSmrg 13701e04c3fSmrg return NULL; 13801e04c3fSmrg} 13901e04c3fSmrg 1407ec681f3Smrg#ifdef WITH_LIBEXPAT 1417ec681f3Smrg 14201e04c3fSmrgstatic void __attribute__((noreturn)) 14301e04c3fSmrgfail(struct location *loc, const char *msg, ...) 14401e04c3fSmrg{ 14501e04c3fSmrg va_list ap; 14601e04c3fSmrg 14701e04c3fSmrg va_start(ap, msg); 14801e04c3fSmrg fprintf(stderr, "%s:%d: error: ", 14901e04c3fSmrg loc->filename, loc->line_number); 15001e04c3fSmrg vfprintf(stderr, msg, ap); 15101e04c3fSmrg fprintf(stderr, "\n"); 15201e04c3fSmrg va_end(ap); 15301e04c3fSmrg exit(EXIT_FAILURE); 15401e04c3fSmrg} 15501e04c3fSmrg 15601e04c3fSmrgstatic void * 15701e04c3fSmrgfail_on_null(void *p) 15801e04c3fSmrg{ 15901e04c3fSmrg if (p == NULL) { 16001e04c3fSmrg fprintf(stderr, "aubinator: out of memory\n"); 16101e04c3fSmrg exit(EXIT_FAILURE); 16201e04c3fSmrg } 16301e04c3fSmrg 16401e04c3fSmrg return p; 16501e04c3fSmrg} 16601e04c3fSmrg 16701e04c3fSmrgstatic char * 16801e04c3fSmrgxstrdup(const char *s) 16901e04c3fSmrg{ 17001e04c3fSmrg return fail_on_null(strdup(s)); 17101e04c3fSmrg} 17201e04c3fSmrg 17301e04c3fSmrgstatic void * 17401e04c3fSmrgzalloc(size_t s) 17501e04c3fSmrg{ 17601e04c3fSmrg return calloc(s, 1); 17701e04c3fSmrg} 17801e04c3fSmrg 17901e04c3fSmrgstatic void * 18001e04c3fSmrgxzalloc(size_t s) 18101e04c3fSmrg{ 18201e04c3fSmrg return fail_on_null(zalloc(s)); 18301e04c3fSmrg} 18401e04c3fSmrg 18501e04c3fSmrg/* We allow fields to have either a bit index, or append "b" for a byte index. 18601e04c3fSmrg */ 18701e04c3fSmrgstatic bool 18801e04c3fSmrgis_byte_offset(const char *value) 18901e04c3fSmrg{ 19001e04c3fSmrg return value[strlen(value) - 1] == 'b'; 19101e04c3fSmrg} 19201e04c3fSmrg 19301e04c3fSmrgstatic void 19401e04c3fSmrgget_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count, 19501e04c3fSmrg uint32_t *size, bool *variable) 19601e04c3fSmrg{ 19701e04c3fSmrg char *p; 19801e04c3fSmrg int i; 19901e04c3fSmrg 20001e04c3fSmrg for (i = 0; atts[i]; i += 2) { 20101e04c3fSmrg if (strcmp(atts[i], "count") == 0) { 20201e04c3fSmrg *count = strtoul(atts[i + 1], &p, 0); 20301e04c3fSmrg if (*count == 0) 20401e04c3fSmrg *variable = true; 20501e04c3fSmrg } else if (strcmp(atts[i], "start") == 0) { 20601e04c3fSmrg *offset = strtoul(atts[i + 1], &p, 0); 20701e04c3fSmrg } else if (strcmp(atts[i], "size") == 0) { 20801e04c3fSmrg *size = strtoul(atts[i + 1], &p, 0); 20901e04c3fSmrg } 21001e04c3fSmrg } 21101e04c3fSmrg return; 21201e04c3fSmrg} 21301e04c3fSmrg 21401e04c3fSmrgstatic struct v3d_group * 21501e04c3fSmrgcreate_group(struct parser_context *ctx, 21601e04c3fSmrg const char *name, 21701e04c3fSmrg const char **atts, 21801e04c3fSmrg struct v3d_group *parent) 21901e04c3fSmrg{ 22001e04c3fSmrg struct v3d_group *group; 22101e04c3fSmrg 22201e04c3fSmrg group = xzalloc(sizeof(*group)); 22301e04c3fSmrg if (name) 22401e04c3fSmrg group->name = xstrdup(name); 22501e04c3fSmrg 22601e04c3fSmrg group->spec = ctx->spec; 22701e04c3fSmrg group->group_offset = 0; 22801e04c3fSmrg group->group_count = 0; 22901e04c3fSmrg group->variable = false; 23001e04c3fSmrg 23101e04c3fSmrg if (parent) { 23201e04c3fSmrg group->parent = parent; 23301e04c3fSmrg get_group_offset_count(atts, 23401e04c3fSmrg &group->group_offset, 23501e04c3fSmrg &group->group_count, 23601e04c3fSmrg &group->group_size, 23701e04c3fSmrg &group->variable); 23801e04c3fSmrg } 23901e04c3fSmrg 24001e04c3fSmrg return group; 24101e04c3fSmrg} 24201e04c3fSmrg 24301e04c3fSmrgstatic struct v3d_enum * 24401e04c3fSmrgcreate_enum(struct parser_context *ctx, const char *name, const char **atts) 24501e04c3fSmrg{ 24601e04c3fSmrg struct v3d_enum *e; 24701e04c3fSmrg 24801e04c3fSmrg e = xzalloc(sizeof(*e)); 24901e04c3fSmrg if (name) 25001e04c3fSmrg e->name = xstrdup(name); 25101e04c3fSmrg 25201e04c3fSmrg e->nvalues = 0; 25301e04c3fSmrg 25401e04c3fSmrg return e; 25501e04c3fSmrg} 25601e04c3fSmrg 25701e04c3fSmrgstatic void 25801e04c3fSmrgget_register_offset(const char **atts, uint32_t *offset) 25901e04c3fSmrg{ 26001e04c3fSmrg char *p; 26101e04c3fSmrg int i; 26201e04c3fSmrg 26301e04c3fSmrg for (i = 0; atts[i]; i += 2) { 26401e04c3fSmrg if (strcmp(atts[i], "num") == 0) 26501e04c3fSmrg *offset = strtoul(atts[i + 1], &p, 0); 26601e04c3fSmrg } 26701e04c3fSmrg return; 26801e04c3fSmrg} 26901e04c3fSmrg 27001e04c3fSmrgstatic void 27101e04c3fSmrgget_start_end_pos(int *start, int *end) 27201e04c3fSmrg{ 27301e04c3fSmrg /* start value has to be mod with 32 as we need the relative 27401e04c3fSmrg * start position in the first DWord. For the end position, add 27501e04c3fSmrg * the length of the field to the start position to get the 27601e04c3fSmrg * relative postion in the 64 bit address. 27701e04c3fSmrg */ 27801e04c3fSmrg if (*end - *start > 32) { 27901e04c3fSmrg int len = *end - *start; 28001e04c3fSmrg *start = *start % 32; 28101e04c3fSmrg *end = *start + len; 28201e04c3fSmrg } else { 28301e04c3fSmrg *start = *start % 32; 28401e04c3fSmrg *end = *end % 32; 28501e04c3fSmrg } 28601e04c3fSmrg 28701e04c3fSmrg return; 28801e04c3fSmrg} 28901e04c3fSmrg 29001e04c3fSmrgstatic inline uint64_t 29101e04c3fSmrgmask(int start, int end) 29201e04c3fSmrg{ 29301e04c3fSmrg uint64_t v; 29401e04c3fSmrg 29501e04c3fSmrg v = ~0ULL >> (63 - end + start); 29601e04c3fSmrg 29701e04c3fSmrg return v << start; 29801e04c3fSmrg} 29901e04c3fSmrg 30001e04c3fSmrgstatic inline uint64_t 30101e04c3fSmrgfield(uint64_t value, int start, int end) 30201e04c3fSmrg{ 30301e04c3fSmrg get_start_end_pos(&start, &end); 30401e04c3fSmrg return (value & mask(start, end)) >> (start); 30501e04c3fSmrg} 30601e04c3fSmrg 30701e04c3fSmrgstatic inline uint64_t 30801e04c3fSmrgfield_address(uint64_t value, int start, int end) 30901e04c3fSmrg{ 31001e04c3fSmrg /* no need to right shift for address/offset */ 31101e04c3fSmrg get_start_end_pos(&start, &end); 31201e04c3fSmrg return (value & mask(start, end)); 31301e04c3fSmrg} 31401e04c3fSmrg 31501e04c3fSmrgstatic struct v3d_type 31601e04c3fSmrgstring_to_type(struct parser_context *ctx, const char *s) 31701e04c3fSmrg{ 31801e04c3fSmrg int i, f; 31901e04c3fSmrg struct v3d_group *g; 32001e04c3fSmrg struct v3d_enum *e; 32101e04c3fSmrg 32201e04c3fSmrg if (strcmp(s, "int") == 0) 32301e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_INT }; 32401e04c3fSmrg else if (strcmp(s, "uint") == 0) 32501e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_UINT }; 32601e04c3fSmrg else if (strcmp(s, "bool") == 0) 32701e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_BOOL }; 32801e04c3fSmrg else if (strcmp(s, "float") == 0) 32901e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_FLOAT }; 33001e04c3fSmrg else if (strcmp(s, "f187") == 0) 33101e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_F187 }; 33201e04c3fSmrg else if (strcmp(s, "address") == 0) 33301e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_ADDRESS }; 33401e04c3fSmrg else if (strcmp(s, "offset") == 0) 33501e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_OFFSET }; 33601e04c3fSmrg else if (sscanf(s, "u%d.%d", &i, &f) == 2) 33701e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_UFIXED, .i = i, .f = f }; 33801e04c3fSmrg else if (sscanf(s, "s%d.%d", &i, &f) == 2) 33901e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_SFIXED, .i = i, .f = f }; 34001e04c3fSmrg else if (g = v3d_spec_find_struct(ctx->spec, s), g != NULL) 34101e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_STRUCT, .v3d_struct = g }; 34201e04c3fSmrg else if (e = v3d_spec_find_enum(ctx->spec, s), e != NULL) 34301e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_ENUM, .v3d_enum = e }; 34401e04c3fSmrg else if (strcmp(s, "mbo") == 0) 34501e04c3fSmrg return (struct v3d_type) { .kind = V3D_TYPE_MBO }; 34601e04c3fSmrg else 34701e04c3fSmrg fail(&ctx->loc, "invalid type: %s", s); 34801e04c3fSmrg} 34901e04c3fSmrg 35001e04c3fSmrgstatic struct v3d_field * 35101e04c3fSmrgcreate_field(struct parser_context *ctx, const char **atts) 35201e04c3fSmrg{ 35301e04c3fSmrg struct v3d_field *field; 35401e04c3fSmrg char *p; 35501e04c3fSmrg int i; 35601e04c3fSmrg uint32_t size = 0; 35701e04c3fSmrg 35801e04c3fSmrg field = xzalloc(sizeof(*field)); 35901e04c3fSmrg 36001e04c3fSmrg for (i = 0; atts[i]; i += 2) { 36101e04c3fSmrg if (strcmp(atts[i], "name") == 0) 36201e04c3fSmrg field->name = xstrdup(atts[i + 1]); 36301e04c3fSmrg else if (strcmp(atts[i], "start") == 0) { 36401e04c3fSmrg field->start = strtoul(atts[i + 1], &p, 0); 36501e04c3fSmrg if (is_byte_offset(atts[i + 1])) 36601e04c3fSmrg field->start *= 8; 36701e04c3fSmrg } else if (strcmp(atts[i], "end") == 0) { 36801e04c3fSmrg field->end = strtoul(atts[i + 1], &p, 0) - 1; 36901e04c3fSmrg if (is_byte_offset(atts[i + 1])) 37001e04c3fSmrg field->end *= 8; 37101e04c3fSmrg } else if (strcmp(atts[i], "size") == 0) { 37201e04c3fSmrg size = strtoul(atts[i + 1], &p, 0); 37301e04c3fSmrg if (is_byte_offset(atts[i + 1])) 37401e04c3fSmrg size *= 8; 37501e04c3fSmrg } else if (strcmp(atts[i], "type") == 0) 37601e04c3fSmrg field->type = string_to_type(ctx, atts[i + 1]); 37701e04c3fSmrg else if (strcmp(atts[i], "default") == 0) { 37801e04c3fSmrg field->has_default = true; 37901e04c3fSmrg field->default_value = strtoul(atts[i + 1], &p, 0); 38001e04c3fSmrg } else if (strcmp(atts[i], "minus_one") == 0) { 38101e04c3fSmrg assert(strcmp(atts[i + 1], "true") == 0); 38201e04c3fSmrg field->minus_one = true; 38301e04c3fSmrg } 38401e04c3fSmrg } 38501e04c3fSmrg 38601e04c3fSmrg if (size) 38701e04c3fSmrg field->end = field->start + size - 1; 38801e04c3fSmrg 38901e04c3fSmrg return field; 39001e04c3fSmrg} 39101e04c3fSmrg 39201e04c3fSmrgstatic struct v3d_value * 39301e04c3fSmrgcreate_value(struct parser_context *ctx, const char **atts) 39401e04c3fSmrg{ 39501e04c3fSmrg struct v3d_value *value = xzalloc(sizeof(*value)); 39601e04c3fSmrg 39701e04c3fSmrg for (int i = 0; atts[i]; i += 2) { 39801e04c3fSmrg if (strcmp(atts[i], "name") == 0) 39901e04c3fSmrg value->name = xstrdup(atts[i + 1]); 40001e04c3fSmrg else if (strcmp(atts[i], "value") == 0) 40101e04c3fSmrg value->value = strtoul(atts[i + 1], NULL, 0); 40201e04c3fSmrg } 40301e04c3fSmrg 40401e04c3fSmrg return value; 40501e04c3fSmrg} 40601e04c3fSmrg 40701e04c3fSmrgstatic void 40801e04c3fSmrgcreate_and_append_field(struct parser_context *ctx, 40901e04c3fSmrg const char **atts) 41001e04c3fSmrg{ 41101e04c3fSmrg if (ctx->group->nfields == ctx->group->fields_size) { 41201e04c3fSmrg ctx->group->fields_size = MAX2(ctx->group->fields_size * 2, 2); 41301e04c3fSmrg ctx->group->fields = 41401e04c3fSmrg (struct v3d_field **) realloc(ctx->group->fields, 41501e04c3fSmrg sizeof(ctx->group->fields[0]) * 41601e04c3fSmrg ctx->group->fields_size); 41701e04c3fSmrg } 41801e04c3fSmrg 41901e04c3fSmrg ctx->group->fields[ctx->group->nfields++] = create_field(ctx, atts); 42001e04c3fSmrg} 42101e04c3fSmrg 42201e04c3fSmrgstatic void 42301e04c3fSmrgset_group_opcode(struct v3d_group *group, const char **atts) 42401e04c3fSmrg{ 42501e04c3fSmrg char *p; 42601e04c3fSmrg int i; 42701e04c3fSmrg 42801e04c3fSmrg for (i = 0; atts[i]; i += 2) { 42901e04c3fSmrg if (strcmp(atts[i], "code") == 0) 43001e04c3fSmrg group->opcode = strtoul(atts[i + 1], &p, 0); 43101e04c3fSmrg } 43201e04c3fSmrg return; 43301e04c3fSmrg} 43401e04c3fSmrg 43501e04c3fSmrgstatic bool 43601e04c3fSmrgver_in_range(int ver, int min_ver, int max_ver) 43701e04c3fSmrg{ 43801e04c3fSmrg return ((min_ver == 0 || ver >= min_ver) && 43901e04c3fSmrg (max_ver == 0 || ver <= max_ver)); 44001e04c3fSmrg} 44101e04c3fSmrg 44201e04c3fSmrgstatic bool 44301e04c3fSmrgskip_if_ver_mismatch(struct parser_context *ctx, int min_ver, int max_ver) 44401e04c3fSmrg{ 44501e04c3fSmrg if (!ctx->parse_skip_depth && !ver_in_range(ctx->devinfo->ver, 44601e04c3fSmrg min_ver, max_ver)) { 44701e04c3fSmrg assert(ctx->parse_depth != 0); 44801e04c3fSmrg ctx->parse_skip_depth = ctx->parse_depth; 44901e04c3fSmrg } 45001e04c3fSmrg 45101e04c3fSmrg return ctx->parse_skip_depth; 45201e04c3fSmrg} 45301e04c3fSmrg 45401e04c3fSmrgstatic void 45501e04c3fSmrgstart_element(void *data, const char *element_name, const char **atts) 45601e04c3fSmrg{ 45701e04c3fSmrg struct parser_context *ctx = data; 45801e04c3fSmrg int i; 45901e04c3fSmrg const char *name = NULL; 46001e04c3fSmrg const char *ver = NULL; 46101e04c3fSmrg int min_ver = 0; 46201e04c3fSmrg int max_ver = 0; 46301e04c3fSmrg 46401e04c3fSmrg ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); 46501e04c3fSmrg 46601e04c3fSmrg for (i = 0; atts[i]; i += 2) { 46701e04c3fSmrg if (strcmp(atts[i], "shortname") == 0) 46801e04c3fSmrg name = atts[i + 1]; 46901e04c3fSmrg else if (strcmp(atts[i], "name") == 0 && !name) 47001e04c3fSmrg name = atts[i + 1]; 47101e04c3fSmrg else if (strcmp(atts[i], "gen") == 0) 47201e04c3fSmrg ver = atts[i + 1]; 47301e04c3fSmrg else if (strcmp(atts[i], "min_ver") == 0) 47401e04c3fSmrg min_ver = strtoul(atts[i + 1], NULL, 0); 47501e04c3fSmrg else if (strcmp(atts[i], "max_ver") == 0) 47601e04c3fSmrg max_ver = strtoul(atts[i + 1], NULL, 0); 47701e04c3fSmrg } 47801e04c3fSmrg 47901e04c3fSmrg if (skip_if_ver_mismatch(ctx, min_ver, max_ver)) 48001e04c3fSmrg goto skip; 48101e04c3fSmrg 48201e04c3fSmrg if (strcmp(element_name, "vcxml") == 0) { 48301e04c3fSmrg if (ver == NULL) 48401e04c3fSmrg fail(&ctx->loc, "no ver given"); 48501e04c3fSmrg 48601e04c3fSmrg /* Make sure that we picked an XML that matched our version. 48701e04c3fSmrg */ 48801e04c3fSmrg assert(ver_in_range(ctx->devinfo->ver, min_ver, max_ver)); 48901e04c3fSmrg 49001e04c3fSmrg int major, minor; 49101e04c3fSmrg int n = sscanf(ver, "%d.%d", &major, &minor); 49201e04c3fSmrg if (n == 0) 49301e04c3fSmrg fail(&ctx->loc, "invalid ver given: %s", ver); 49401e04c3fSmrg if (n == 1) 49501e04c3fSmrg minor = 0; 49601e04c3fSmrg 49701e04c3fSmrg ctx->spec->ver = major * 10 + minor; 49801e04c3fSmrg } else if (strcmp(element_name, "packet") == 0 || 49901e04c3fSmrg strcmp(element_name, "struct") == 0) { 50001e04c3fSmrg ctx->group = create_group(ctx, name, atts, NULL); 50101e04c3fSmrg 50201e04c3fSmrg if (strcmp(element_name, "packet") == 0) 50301e04c3fSmrg set_group_opcode(ctx->group, atts); 50401e04c3fSmrg } else if (strcmp(element_name, "register") == 0) { 50501e04c3fSmrg ctx->group = create_group(ctx, name, atts, NULL); 50601e04c3fSmrg get_register_offset(atts, &ctx->group->register_offset); 50701e04c3fSmrg } else if (strcmp(element_name, "group") == 0) { 50801e04c3fSmrg struct v3d_group *previous_group = ctx->group; 50901e04c3fSmrg while (previous_group->next) 51001e04c3fSmrg previous_group = previous_group->next; 51101e04c3fSmrg 51201e04c3fSmrg struct v3d_group *group = create_group(ctx, "", atts, 51301e04c3fSmrg ctx->group); 51401e04c3fSmrg previous_group->next = group; 51501e04c3fSmrg ctx->group = group; 51601e04c3fSmrg } else if (strcmp(element_name, "field") == 0) { 51701e04c3fSmrg create_and_append_field(ctx, atts); 51801e04c3fSmrg } else if (strcmp(element_name, "enum") == 0) { 51901e04c3fSmrg ctx->enoom = create_enum(ctx, name, atts); 52001e04c3fSmrg } else if (strcmp(element_name, "value") == 0) { 52101e04c3fSmrg ctx->values[ctx->nvalues++] = create_value(ctx, atts); 52201e04c3fSmrg assert(ctx->nvalues < ARRAY_SIZE(ctx->values)); 52301e04c3fSmrg } 52401e04c3fSmrg 52501e04c3fSmrgskip: 52601e04c3fSmrg ctx->parse_depth++; 52701e04c3fSmrg} 52801e04c3fSmrg 52901e04c3fSmrgstatic int 53001e04c3fSmrgfield_offset_compare(const void *a, const void *b) 53101e04c3fSmrg{ 53201e04c3fSmrg return ((*(const struct v3d_field **)a)->start - 53301e04c3fSmrg (*(const struct v3d_field **)b)->start); 53401e04c3fSmrg} 53501e04c3fSmrg 53601e04c3fSmrgstatic void 53701e04c3fSmrgend_element(void *data, const char *name) 53801e04c3fSmrg{ 53901e04c3fSmrg struct parser_context *ctx = data; 54001e04c3fSmrg struct v3d_spec *spec = ctx->spec; 54101e04c3fSmrg 54201e04c3fSmrg ctx->parse_depth--; 54301e04c3fSmrg 54401e04c3fSmrg if (ctx->parse_skip_depth) { 54501e04c3fSmrg if (ctx->parse_skip_depth == ctx->parse_depth) 54601e04c3fSmrg ctx->parse_skip_depth = 0; 54701e04c3fSmrg return; 54801e04c3fSmrg } 54901e04c3fSmrg 55001e04c3fSmrg if (strcmp(name, "packet") == 0 || 55101e04c3fSmrg strcmp(name, "struct") == 0 || 55201e04c3fSmrg strcmp(name, "register") == 0) { 55301e04c3fSmrg struct v3d_group *group = ctx->group; 55401e04c3fSmrg 55501e04c3fSmrg ctx->group = ctx->group->parent; 55601e04c3fSmrg 55701e04c3fSmrg if (strcmp(name, "packet") == 0) { 55801e04c3fSmrg spec->commands[spec->ncommands++] = group; 55901e04c3fSmrg 56001e04c3fSmrg /* V3D packet XML has the packet contents with offsets 56101e04c3fSmrg * starting from the first bit after the opcode, to 56201e04c3fSmrg * match the spec. Shift the fields up now. 56301e04c3fSmrg */ 56401e04c3fSmrg for (int i = 0; i < group->nfields; i++) { 56501e04c3fSmrg group->fields[i]->start += 8; 56601e04c3fSmrg group->fields[i]->end += 8; 56701e04c3fSmrg } 56801e04c3fSmrg } 56901e04c3fSmrg else if (strcmp(name, "struct") == 0) 57001e04c3fSmrg spec->structs[spec->nstructs++] = group; 57101e04c3fSmrg else if (strcmp(name, "register") == 0) 57201e04c3fSmrg spec->registers[spec->nregisters++] = group; 57301e04c3fSmrg 57401e04c3fSmrg /* Sort the fields in increasing offset order. The XML might 57501e04c3fSmrg * be specified in any order, but we'll want to iterate from 57601e04c3fSmrg * the bottom. 57701e04c3fSmrg */ 57801e04c3fSmrg qsort(group->fields, group->nfields, sizeof(*group->fields), 57901e04c3fSmrg field_offset_compare); 58001e04c3fSmrg 58101e04c3fSmrg assert(spec->ncommands < ARRAY_SIZE(spec->commands)); 58201e04c3fSmrg assert(spec->nstructs < ARRAY_SIZE(spec->structs)); 58301e04c3fSmrg assert(spec->nregisters < ARRAY_SIZE(spec->registers)); 58401e04c3fSmrg } else if (strcmp(name, "group") == 0) { 58501e04c3fSmrg ctx->group = ctx->group->parent; 58601e04c3fSmrg } else if (strcmp(name, "field") == 0) { 58701e04c3fSmrg assert(ctx->group->nfields > 0); 58801e04c3fSmrg struct v3d_field *field = ctx->group->fields[ctx->group->nfields - 1]; 58901e04c3fSmrg size_t size = ctx->nvalues * sizeof(ctx->values[0]); 59001e04c3fSmrg field->inline_enum.values = xzalloc(size); 59101e04c3fSmrg field->inline_enum.nvalues = ctx->nvalues; 59201e04c3fSmrg memcpy(field->inline_enum.values, ctx->values, size); 59301e04c3fSmrg ctx->nvalues = 0; 59401e04c3fSmrg } else if (strcmp(name, "enum") == 0) { 59501e04c3fSmrg struct v3d_enum *e = ctx->enoom; 59601e04c3fSmrg size_t size = ctx->nvalues * sizeof(ctx->values[0]); 59701e04c3fSmrg e->values = xzalloc(size); 59801e04c3fSmrg e->nvalues = ctx->nvalues; 59901e04c3fSmrg memcpy(e->values, ctx->values, size); 60001e04c3fSmrg ctx->nvalues = 0; 60101e04c3fSmrg ctx->enoom = NULL; 60201e04c3fSmrg spec->enums[spec->nenums++] = e; 60301e04c3fSmrg } 60401e04c3fSmrg} 60501e04c3fSmrg 60601e04c3fSmrgstatic void 60701e04c3fSmrgcharacter_data(void *data, const XML_Char *s, int len) 60801e04c3fSmrg{ 60901e04c3fSmrg} 61001e04c3fSmrg 61101e04c3fSmrgstatic uint32_t zlib_inflate(const void *compressed_data, 61201e04c3fSmrg uint32_t compressed_len, 61301e04c3fSmrg void **out_ptr) 61401e04c3fSmrg{ 61501e04c3fSmrg struct z_stream_s zstream; 61601e04c3fSmrg void *out; 61701e04c3fSmrg 61801e04c3fSmrg memset(&zstream, 0, sizeof(zstream)); 61901e04c3fSmrg 62001e04c3fSmrg zstream.next_in = (unsigned char *)compressed_data; 62101e04c3fSmrg zstream.avail_in = compressed_len; 62201e04c3fSmrg 62301e04c3fSmrg if (inflateInit(&zstream) != Z_OK) 62401e04c3fSmrg return 0; 62501e04c3fSmrg 62601e04c3fSmrg out = malloc(4096); 62701e04c3fSmrg zstream.next_out = out; 62801e04c3fSmrg zstream.avail_out = 4096; 62901e04c3fSmrg 63001e04c3fSmrg do { 63101e04c3fSmrg switch (inflate(&zstream, Z_SYNC_FLUSH)) { 63201e04c3fSmrg case Z_STREAM_END: 63301e04c3fSmrg goto end; 63401e04c3fSmrg case Z_OK: 63501e04c3fSmrg break; 63601e04c3fSmrg default: 63701e04c3fSmrg inflateEnd(&zstream); 63801e04c3fSmrg return 0; 63901e04c3fSmrg } 64001e04c3fSmrg 64101e04c3fSmrg if (zstream.avail_out) 64201e04c3fSmrg break; 64301e04c3fSmrg 64401e04c3fSmrg out = realloc(out, 2*zstream.total_out); 64501e04c3fSmrg if (out == NULL) { 64601e04c3fSmrg inflateEnd(&zstream); 64701e04c3fSmrg return 0; 64801e04c3fSmrg } 64901e04c3fSmrg 65001e04c3fSmrg zstream.next_out = (unsigned char *)out + zstream.total_out; 65101e04c3fSmrg zstream.avail_out = zstream.total_out; 65201e04c3fSmrg } while (1); 65301e04c3fSmrg end: 65401e04c3fSmrg inflateEnd(&zstream); 65501e04c3fSmrg *out_ptr = out; 65601e04c3fSmrg return zstream.total_out; 65701e04c3fSmrg} 65801e04c3fSmrg 6597ec681f3Smrg#endif /* WITH_LIBEXPAT */ 6607ec681f3Smrg 66101e04c3fSmrgstruct v3d_spec * 66201e04c3fSmrgv3d_spec_load(const struct v3d_device_info *devinfo) 66301e04c3fSmrg{ 6647ec681f3Smrg struct v3d_spec *spec = calloc(1, sizeof(struct v3d_spec)); 6657ec681f3Smrg if (!spec) 6667ec681f3Smrg return NULL; 6677ec681f3Smrg 6687ec681f3Smrg#ifdef WITH_LIBEXPAT 66901e04c3fSmrg struct parser_context ctx; 67001e04c3fSmrg void *buf; 67101e04c3fSmrg uint8_t *text_data = NULL; 672ed98bd31Smaya uint32_t text_offset = 0, text_length = 0; 6737ec681f3Smrg ASSERTED uint32_t total_length; 67401e04c3fSmrg 67501e04c3fSmrg for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) { 67601e04c3fSmrg if (i != 0) { 6777ec681f3Smrg assert(genxml_files_table[i - 1].ver_10 < 6787ec681f3Smrg genxml_files_table[i].ver_10); 67901e04c3fSmrg } 68001e04c3fSmrg 6817ec681f3Smrg if (genxml_files_table[i].ver_10 <= devinfo->ver) { 68201e04c3fSmrg text_offset = genxml_files_table[i].offset; 68301e04c3fSmrg text_length = genxml_files_table[i].length; 68401e04c3fSmrg } 68501e04c3fSmrg } 68601e04c3fSmrg 68701e04c3fSmrg if (text_length == 0) { 68801e04c3fSmrg fprintf(stderr, "unable to find gen (%u) data\n", devinfo->ver); 6897ec681f3Smrg free(spec); 69001e04c3fSmrg return NULL; 69101e04c3fSmrg } 69201e04c3fSmrg 69301e04c3fSmrg memset(&ctx, 0, sizeof ctx); 69401e04c3fSmrg ctx.parser = XML_ParserCreate(NULL); 69501e04c3fSmrg ctx.devinfo = devinfo; 69601e04c3fSmrg XML_SetUserData(ctx.parser, &ctx); 69701e04c3fSmrg if (ctx.parser == NULL) { 69801e04c3fSmrg fprintf(stderr, "failed to create parser\n"); 6997ec681f3Smrg free(spec); 70001e04c3fSmrg return NULL; 70101e04c3fSmrg } 70201e04c3fSmrg 70301e04c3fSmrg XML_SetElementHandler(ctx.parser, start_element, end_element); 70401e04c3fSmrg XML_SetCharacterDataHandler(ctx.parser, character_data); 70501e04c3fSmrg 7067ec681f3Smrg ctx.spec = spec; 70701e04c3fSmrg 70801e04c3fSmrg total_length = zlib_inflate(compress_genxmls, 70901e04c3fSmrg sizeof(compress_genxmls), 71001e04c3fSmrg (void **) &text_data); 71101e04c3fSmrg assert(text_offset + text_length <= total_length); 71201e04c3fSmrg 71301e04c3fSmrg buf = XML_GetBuffer(ctx.parser, text_length); 71401e04c3fSmrg memcpy(buf, &text_data[text_offset], text_length); 71501e04c3fSmrg 71601e04c3fSmrg if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) { 71701e04c3fSmrg fprintf(stderr, 71801e04c3fSmrg "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n", 71901e04c3fSmrg XML_GetCurrentLineNumber(ctx.parser), 72001e04c3fSmrg XML_GetCurrentColumnNumber(ctx.parser), 72101e04c3fSmrg XML_GetCurrentByteIndex(ctx.parser), text_length, 72201e04c3fSmrg XML_ErrorString(XML_GetErrorCode(ctx.parser))); 72301e04c3fSmrg XML_ParserFree(ctx.parser); 72401e04c3fSmrg free(text_data); 7257ec681f3Smrg free(spec); 72601e04c3fSmrg return NULL; 72701e04c3fSmrg } 72801e04c3fSmrg 72901e04c3fSmrg XML_ParserFree(ctx.parser); 73001e04c3fSmrg free(text_data); 73101e04c3fSmrg 73201e04c3fSmrg return ctx.spec; 7337ec681f3Smrg#else /* !WITH_LIBEXPAT */ 7347ec681f3Smrg debug_warn_once("CLIF dumping not supported due to missing libexpat"); 7357ec681f3Smrg return spec; 7367ec681f3Smrg#endif /* !WITH_LIBEXPAT */ 73701e04c3fSmrg} 73801e04c3fSmrg 73901e04c3fSmrgstruct v3d_group * 74001e04c3fSmrgv3d_spec_find_instruction(struct v3d_spec *spec, const uint8_t *p) 74101e04c3fSmrg{ 74201e04c3fSmrg uint8_t opcode = *p; 74301e04c3fSmrg 74401e04c3fSmrg for (int i = 0; i < spec->ncommands; i++) { 74501e04c3fSmrg struct v3d_group *group = spec->commands[i]; 74601e04c3fSmrg 74701e04c3fSmrg if (opcode != group->opcode) 74801e04c3fSmrg continue; 74901e04c3fSmrg 75001e04c3fSmrg /* If there's a "sub-id" field, make sure that it matches the 75101e04c3fSmrg * instruction being decoded. 75201e04c3fSmrg */ 75301e04c3fSmrg struct v3d_field *subid = NULL; 75401e04c3fSmrg for (int j = 0; j < group->nfields; j++) { 75501e04c3fSmrg struct v3d_field *field = group->fields[j]; 75601e04c3fSmrg if (strcmp(field->name, "sub-id") == 0) { 75701e04c3fSmrg subid = field; 75801e04c3fSmrg break; 75901e04c3fSmrg } 76001e04c3fSmrg } 76101e04c3fSmrg 76201e04c3fSmrg if (subid && (__gen_unpack_uint(p, subid->start, subid->end) != 76301e04c3fSmrg subid->default_value)) { 76401e04c3fSmrg continue; 76501e04c3fSmrg } 76601e04c3fSmrg 76701e04c3fSmrg return group; 76801e04c3fSmrg } 76901e04c3fSmrg 77001e04c3fSmrg return NULL; 77101e04c3fSmrg} 77201e04c3fSmrg 77301e04c3fSmrg/** Returns the size of a V3D packet. */ 77401e04c3fSmrgint 77501e04c3fSmrgv3d_group_get_length(struct v3d_group *group) 77601e04c3fSmrg{ 77701e04c3fSmrg int last_bit = 0; 77801e04c3fSmrg for (int i = 0; i < group->nfields; i++) { 77901e04c3fSmrg struct v3d_field *field = group->fields[i]; 78001e04c3fSmrg 78101e04c3fSmrg last_bit = MAX2(last_bit, field->end); 78201e04c3fSmrg } 78301e04c3fSmrg return last_bit / 8 + 1; 78401e04c3fSmrg} 78501e04c3fSmrg 78601e04c3fSmrgvoid 78701e04c3fSmrgv3d_field_iterator_init(struct v3d_field_iterator *iter, 78801e04c3fSmrg struct v3d_group *group, 78901e04c3fSmrg const uint8_t *p) 79001e04c3fSmrg{ 79101e04c3fSmrg memset(iter, 0, sizeof(*iter)); 79201e04c3fSmrg 79301e04c3fSmrg iter->group = group; 79401e04c3fSmrg iter->p = p; 79501e04c3fSmrg} 79601e04c3fSmrg 79701e04c3fSmrgstatic const char * 79801e04c3fSmrgv3d_get_enum_name(struct v3d_enum *e, uint64_t value) 79901e04c3fSmrg{ 80001e04c3fSmrg for (int i = 0; i < e->nvalues; i++) { 80101e04c3fSmrg if (e->values[i]->value == value) { 80201e04c3fSmrg return e->values[i]->name; 80301e04c3fSmrg } 80401e04c3fSmrg } 80501e04c3fSmrg return NULL; 80601e04c3fSmrg} 80701e04c3fSmrg 80801e04c3fSmrgstatic bool 80901e04c3fSmrgiter_more_fields(const struct v3d_field_iterator *iter) 81001e04c3fSmrg{ 81101e04c3fSmrg return iter->field_iter < iter->group->nfields; 81201e04c3fSmrg} 81301e04c3fSmrg 81401e04c3fSmrgstatic uint32_t 81501e04c3fSmrgiter_group_offset_bits(const struct v3d_field_iterator *iter, 81601e04c3fSmrg uint32_t group_iter) 81701e04c3fSmrg{ 81801e04c3fSmrg return iter->group->group_offset + (group_iter * 81901e04c3fSmrg iter->group->group_size); 82001e04c3fSmrg} 82101e04c3fSmrg 82201e04c3fSmrgstatic bool 82301e04c3fSmrgiter_more_groups(const struct v3d_field_iterator *iter) 82401e04c3fSmrg{ 82501e04c3fSmrg if (iter->group->variable) { 82601e04c3fSmrg return iter_group_offset_bits(iter, iter->group_iter + 1) < 82701e04c3fSmrg (v3d_group_get_length(iter->group) * 8); 82801e04c3fSmrg } else { 82901e04c3fSmrg return (iter->group_iter + 1) < iter->group->group_count || 83001e04c3fSmrg iter->group->next != NULL; 83101e04c3fSmrg } 83201e04c3fSmrg} 83301e04c3fSmrg 83401e04c3fSmrgstatic void 83501e04c3fSmrgiter_advance_group(struct v3d_field_iterator *iter) 83601e04c3fSmrg{ 83701e04c3fSmrg if (iter->group->variable) 83801e04c3fSmrg iter->group_iter++; 83901e04c3fSmrg else { 84001e04c3fSmrg if ((iter->group_iter + 1) < iter->group->group_count) { 84101e04c3fSmrg iter->group_iter++; 84201e04c3fSmrg } else { 84301e04c3fSmrg iter->group = iter->group->next; 84401e04c3fSmrg iter->group_iter = 0; 84501e04c3fSmrg } 84601e04c3fSmrg } 84701e04c3fSmrg 84801e04c3fSmrg iter->field_iter = 0; 84901e04c3fSmrg} 85001e04c3fSmrg 85101e04c3fSmrgstatic bool 85201e04c3fSmrgiter_advance_field(struct v3d_field_iterator *iter) 85301e04c3fSmrg{ 85401e04c3fSmrg while (!iter_more_fields(iter)) { 85501e04c3fSmrg if (!iter_more_groups(iter)) 85601e04c3fSmrg return false; 85701e04c3fSmrg 85801e04c3fSmrg iter_advance_group(iter); 85901e04c3fSmrg } 86001e04c3fSmrg 86101e04c3fSmrg iter->field = iter->group->fields[iter->field_iter++]; 86201e04c3fSmrg if (iter->field->name) 86301e04c3fSmrg snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name); 86401e04c3fSmrg else 86501e04c3fSmrg memset(iter->name, 0, sizeof(iter->name)); 86601e04c3fSmrg iter->offset = iter_group_offset_bits(iter, iter->group_iter) / 8 + 86701e04c3fSmrg iter->field->start / 8; 86801e04c3fSmrg iter->struct_desc = NULL; 86901e04c3fSmrg 87001e04c3fSmrg return true; 87101e04c3fSmrg} 87201e04c3fSmrg 87301e04c3fSmrgbool 87401e04c3fSmrgv3d_field_iterator_next(struct clif_dump *clif, struct v3d_field_iterator *iter) 87501e04c3fSmrg{ 87601e04c3fSmrg if (!iter_advance_field(iter)) 87701e04c3fSmrg return false; 87801e04c3fSmrg 87901e04c3fSmrg const char *enum_name = NULL; 88001e04c3fSmrg 88101e04c3fSmrg int group_member_offset = 88201e04c3fSmrg iter_group_offset_bits(iter, iter->group_iter); 88301e04c3fSmrg int s = group_member_offset + iter->field->start; 88401e04c3fSmrg int e = group_member_offset + iter->field->end; 88501e04c3fSmrg 88601e04c3fSmrg assert(!iter->field->minus_one || 88701e04c3fSmrg iter->field->type.kind == V3D_TYPE_INT || 88801e04c3fSmrg iter->field->type.kind == V3D_TYPE_UINT); 88901e04c3fSmrg 89001e04c3fSmrg switch (iter->field->type.kind) { 89101e04c3fSmrg case V3D_TYPE_UNKNOWN: 89201e04c3fSmrg case V3D_TYPE_INT: { 89301e04c3fSmrg uint32_t value = __gen_unpack_sint(iter->p, s, e); 89401e04c3fSmrg if (iter->field->minus_one) 89501e04c3fSmrg value++; 89601e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%d", value); 89701e04c3fSmrg enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); 89801e04c3fSmrg break; 89901e04c3fSmrg } 90001e04c3fSmrg case V3D_TYPE_UINT: { 90101e04c3fSmrg uint32_t value = __gen_unpack_uint(iter->p, s, e); 90201e04c3fSmrg if (iter->field->minus_one) 90301e04c3fSmrg value++; 90401e04c3fSmrg if (strcmp(iter->field->name, "Vec size") == 0 && value == 0) 9057ec681f3Smrg value = 1 << (e - s + 1); 90601e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%u", value); 90701e04c3fSmrg enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); 90801e04c3fSmrg break; 90901e04c3fSmrg } 91001e04c3fSmrg case V3D_TYPE_BOOL: 91101e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%s", 91201e04c3fSmrg __gen_unpack_uint(iter->p, s, e) ? 91301e04c3fSmrg "1 /* true */" : "0 /* false */"); 91401e04c3fSmrg break; 91501e04c3fSmrg case V3D_TYPE_FLOAT: 91601e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%f", 91701e04c3fSmrg __gen_unpack_float(iter->p, s, e)); 91801e04c3fSmrg break; 91901e04c3fSmrg 92001e04c3fSmrg case V3D_TYPE_F187: 92101e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%f", 92201e04c3fSmrg __gen_unpack_f187(iter->p, s, e)); 92301e04c3fSmrg break; 92401e04c3fSmrg 92501e04c3fSmrg case V3D_TYPE_ADDRESS: { 92601e04c3fSmrg uint32_t addr = 92701e04c3fSmrg __gen_unpack_uint(iter->p, s, e) << (31 - (e - s)); 92801e04c3fSmrg struct clif_bo *bo = clif_lookup_bo(clif, addr); 92901e04c3fSmrg if (bo) { 93001e04c3fSmrg snprintf(iter->value, sizeof(iter->value), 93101e04c3fSmrg "[%s+0x%08x] /* 0x%08x */", 93201e04c3fSmrg bo->name, addr - bo->offset, addr); 93301e04c3fSmrg } else if (addr) { 93401e04c3fSmrg snprintf(iter->value, sizeof(iter->value), 93501e04c3fSmrg "/* XXX: BO unknown */ 0x%08x", addr); 93601e04c3fSmrg } else { 93701e04c3fSmrg snprintf(iter->value, sizeof(iter->value), 93801e04c3fSmrg "[null]"); 93901e04c3fSmrg } 94001e04c3fSmrg 94101e04c3fSmrg break; 94201e04c3fSmrg } 94301e04c3fSmrg 94401e04c3fSmrg case V3D_TYPE_OFFSET: 94501e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, 94601e04c3fSmrg __gen_unpack_uint(iter->p, s, e) << (31 - (e - s))); 94701e04c3fSmrg break; 94801e04c3fSmrg case V3D_TYPE_STRUCT: 94901e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "<struct %s>", 95001e04c3fSmrg iter->field->type.v3d_struct->name); 95101e04c3fSmrg iter->struct_desc = 95201e04c3fSmrg v3d_spec_find_struct(iter->group->spec, 95301e04c3fSmrg iter->field->type.v3d_struct->name); 95401e04c3fSmrg break; 95501e04c3fSmrg case V3D_TYPE_SFIXED: 95601e04c3fSmrg if (clif->pretty) { 95701e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%f", 95801e04c3fSmrg __gen_unpack_sfixed(iter->p, s, e, 95901e04c3fSmrg iter->field->type.f)); 96001e04c3fSmrg } else { 96101e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%u", 96201e04c3fSmrg (unsigned)__gen_unpack_uint(iter->p, s, e)); 96301e04c3fSmrg } 96401e04c3fSmrg break; 96501e04c3fSmrg case V3D_TYPE_UFIXED: 96601e04c3fSmrg if (clif->pretty) { 96701e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%f", 96801e04c3fSmrg __gen_unpack_ufixed(iter->p, s, e, 96901e04c3fSmrg iter->field->type.f)); 97001e04c3fSmrg } else { 97101e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%u", 97201e04c3fSmrg (unsigned)__gen_unpack_uint(iter->p, s, e)); 97301e04c3fSmrg } 97401e04c3fSmrg break; 97501e04c3fSmrg case V3D_TYPE_MBO: 97601e04c3fSmrg break; 97701e04c3fSmrg case V3D_TYPE_ENUM: { 97801e04c3fSmrg uint32_t value = __gen_unpack_uint(iter->p, s, e); 97901e04c3fSmrg snprintf(iter->value, sizeof(iter->value), "%d", value); 98001e04c3fSmrg enum_name = v3d_get_enum_name(iter->field->type.v3d_enum, value); 98101e04c3fSmrg break; 98201e04c3fSmrg } 98301e04c3fSmrg } 98401e04c3fSmrg 98501e04c3fSmrg if (strlen(iter->group->name) == 0) { 98601e04c3fSmrg int length = strlen(iter->name); 98701e04c3fSmrg snprintf(iter->name + length, sizeof(iter->name) - length, 98801e04c3fSmrg "[%i]", iter->group_iter); 98901e04c3fSmrg } 99001e04c3fSmrg 99101e04c3fSmrg if (enum_name) { 99201e04c3fSmrg int length = strlen(iter->value); 99301e04c3fSmrg snprintf(iter->value + length, sizeof(iter->value) - length, 99401e04c3fSmrg " /* %s */", enum_name); 99501e04c3fSmrg } 99601e04c3fSmrg 99701e04c3fSmrg return true; 99801e04c3fSmrg} 99901e04c3fSmrg 100001e04c3fSmrgvoid 100101e04c3fSmrgv3d_print_group(struct clif_dump *clif, struct v3d_group *group, 100201e04c3fSmrg uint64_t offset, const uint8_t *p) 100301e04c3fSmrg{ 100401e04c3fSmrg struct v3d_field_iterator iter; 100501e04c3fSmrg 100601e04c3fSmrg v3d_field_iterator_init(&iter, group, p); 100701e04c3fSmrg while (v3d_field_iterator_next(clif, &iter)) { 100801e04c3fSmrg /* Clif parsing uses the packet name, and expects no 100901e04c3fSmrg * sub-id. 101001e04c3fSmrg */ 101101e04c3fSmrg if (strcmp(iter.field->name, "sub-id") == 0 || 101201e04c3fSmrg strcmp(iter.field->name, "unused") == 0 || 101301e04c3fSmrg strcmp(iter.field->name, "Pad") == 0) 101401e04c3fSmrg continue; 101501e04c3fSmrg 101601e04c3fSmrg if (clif->pretty) { 101701e04c3fSmrg fprintf(clif->out, " %s: %s\n", 101801e04c3fSmrg iter.name, iter.value); 101901e04c3fSmrg } else { 102001e04c3fSmrg fprintf(clif->out, " /* %30s: */ %s\n", 102101e04c3fSmrg iter.name, iter.value); 102201e04c3fSmrg } 102301e04c3fSmrg if (iter.struct_desc) { 102401e04c3fSmrg uint64_t struct_offset = offset + iter.offset; 102501e04c3fSmrg v3d_print_group(clif, iter.struct_desc, 102601e04c3fSmrg struct_offset, 102701e04c3fSmrg &p[iter.offset]); 102801e04c3fSmrg } 102901e04c3fSmrg } 103001e04c3fSmrg} 1031