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