2 * Copyright © 2016 Intel Corporation
3 * Copyright © 2017 Broadcom
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 #include <util/macros.h>
35 #include <util/ralloc.h>
37 #include "v3d_decoder.h"
38 #include "v3d_packet_helpers.h"
40 #include "broadcom/clif/clif_private.h"
46 struct v3d_group
*commands
[256];
48 struct v3d_group
*structs
[256];
50 struct v3d_group
*registers
[256];
52 struct v3d_enum
*enums
[256];
60 struct parser_context
{
62 const struct v3d_device_info
*devinfo
;
66 struct v3d_group
*group
;
67 struct v3d_enum
*enoom
;
70 struct v3d_value
*values
[256];
72 struct v3d_spec
*spec
;
79 v3d_group_get_name(struct v3d_group
*group
)
85 v3d_group_get_opcode(struct v3d_group
*group
)
91 v3d_spec_find_struct(struct v3d_spec
*spec
, const char *name
)
93 for (int i
= 0; i
< spec
->nstructs
; i
++)
94 if (strcmp(spec
->structs
[i
]->name
, name
) == 0)
95 return spec
->structs
[i
];
101 v3d_spec_find_register(struct v3d_spec
*spec
, uint32_t offset
)
103 for (int i
= 0; i
< spec
->nregisters
; i
++)
104 if (spec
->registers
[i
]->register_offset
== offset
)
105 return spec
->registers
[i
];
111 v3d_spec_find_register_by_name(struct v3d_spec
*spec
, const char *name
)
113 for (int i
= 0; i
< spec
->nregisters
; i
++) {
114 if (strcmp(spec
->registers
[i
]->name
, name
) == 0)
115 return spec
->registers
[i
];
122 v3d_spec_find_enum(struct v3d_spec
*spec
, const char *name
)
124 for (int i
= 0; i
< spec
->nenums
; i
++)
125 if (strcmp(spec
->enums
[i
]->name
, name
) == 0)
126 return spec
->enums
[i
];
131 static void __attribute__((noreturn
))
132 fail(struct location
*loc
, const char *msg
, ...)
137 fprintf(stderr
, "%s:%d: error: ",
138 loc
->filename
, loc
->line_number
);
139 vfprintf(stderr
, msg
, ap
);
140 fprintf(stderr
, "\n");
146 fail_on_null(void *p
)
149 fprintf(stderr
, "aubinator: out of memory\n");
157 xstrdup(const char *s
)
159 return fail_on_null(strdup(s
));
171 return fail_on_null(zalloc(s
));
174 /* We allow fields to have either a bit index, or append "b" for a byte index.
177 is_byte_offset(const char *value
)
179 return value
[strlen(value
) - 1] == 'b';
183 get_group_offset_count(const char **atts
, uint32_t *offset
, uint32_t *count
,
184 uint32_t *size
, bool *variable
)
189 for (i
= 0; atts
[i
]; i
+= 2) {
190 if (strcmp(atts
[i
], "count") == 0) {
191 *count
= strtoul(atts
[i
+ 1], &p
, 0);
194 } else if (strcmp(atts
[i
], "start") == 0) {
195 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
196 } else if (strcmp(atts
[i
], "size") == 0) {
197 *size
= strtoul(atts
[i
+ 1], &p
, 0);
203 static struct v3d_group
*
204 create_group(struct parser_context
*ctx
,
207 struct v3d_group
*parent
)
209 struct v3d_group
*group
;
211 group
= xzalloc(sizeof(*group
));
213 group
->name
= xstrdup(name
);
215 group
->spec
= ctx
->spec
;
216 group
->group_offset
= 0;
217 group
->group_count
= 0;
218 group
->variable
= false;
221 group
->parent
= parent
;
222 get_group_offset_count(atts
,
223 &group
->group_offset
,
232 static struct v3d_enum
*
233 create_enum(struct parser_context
*ctx
, const char *name
, const char **atts
)
237 e
= xzalloc(sizeof(*e
));
239 e
->name
= xstrdup(name
);
247 get_register_offset(const char **atts
, uint32_t *offset
)
252 for (i
= 0; atts
[i
]; i
+= 2) {
253 if (strcmp(atts
[i
], "num") == 0)
254 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
260 get_start_end_pos(int *start
, int *end
)
262 /* start value has to be mod with 32 as we need the relative
263 * start position in the first DWord. For the end position, add
264 * the length of the field to the start position to get the
265 * relative postion in the 64 bit address.
267 if (*end
- *start
> 32) {
268 int len
= *end
- *start
;
269 *start
= *start
% 32;
272 *start
= *start
% 32;
279 static inline uint64_t
280 mask(int start
, int end
)
284 v
= ~0ULL >> (63 - end
+ start
);
289 static inline uint64_t
290 field(uint64_t value
, int start
, int end
)
292 get_start_end_pos(&start
, &end
);
293 return (value
& mask(start
, end
)) >> (start
);
296 static inline uint64_t
297 field_address(uint64_t value
, int start
, int end
)
299 /* no need to right shift for address/offset */
300 get_start_end_pos(&start
, &end
);
301 return (value
& mask(start
, end
));
304 static struct v3d_type
305 string_to_type(struct parser_context
*ctx
, const char *s
)
311 if (strcmp(s
, "int") == 0)
312 return (struct v3d_type
) { .kind
= V3D_TYPE_INT
};
313 else if (strcmp(s
, "uint") == 0)
314 return (struct v3d_type
) { .kind
= V3D_TYPE_UINT
};
315 else if (strcmp(s
, "bool") == 0)
316 return (struct v3d_type
) { .kind
= V3D_TYPE_BOOL
};
317 else if (strcmp(s
, "float") == 0)
318 return (struct v3d_type
) { .kind
= V3D_TYPE_FLOAT
};
319 else if (strcmp(s
, "f187") == 0)
320 return (struct v3d_type
) { .kind
= V3D_TYPE_F187
};
321 else if (strcmp(s
, "address") == 0)
322 return (struct v3d_type
) { .kind
= V3D_TYPE_ADDRESS
};
323 else if (strcmp(s
, "offset") == 0)
324 return (struct v3d_type
) { .kind
= V3D_TYPE_OFFSET
};
325 else if (sscanf(s
, "u%d.%d", &i
, &f
) == 2)
326 return (struct v3d_type
) { .kind
= V3D_TYPE_UFIXED
, .i
= i
, .f
= f
};
327 else if (sscanf(s
, "s%d.%d", &i
, &f
) == 2)
328 return (struct v3d_type
) { .kind
= V3D_TYPE_SFIXED
, .i
= i
, .f
= f
};
329 else if (g
= v3d_spec_find_struct(ctx
->spec
, s
), g
!= NULL
)
330 return (struct v3d_type
) { .kind
= V3D_TYPE_STRUCT
, .v3d_struct
= g
};
331 else if (e
= v3d_spec_find_enum(ctx
->spec
, s
), e
!= NULL
)
332 return (struct v3d_type
) { .kind
= V3D_TYPE_ENUM
, .v3d_enum
= e
};
333 else if (strcmp(s
, "mbo") == 0)
334 return (struct v3d_type
) { .kind
= V3D_TYPE_MBO
};
336 fail(&ctx
->loc
, "invalid type: %s", s
);
339 static struct v3d_field
*
340 create_field(struct parser_context
*ctx
, const char **atts
)
342 struct v3d_field
*field
;
347 field
= xzalloc(sizeof(*field
));
349 for (i
= 0; atts
[i
]; i
+= 2) {
350 if (strcmp(atts
[i
], "name") == 0)
351 field
->name
= xstrdup(atts
[i
+ 1]);
352 else if (strcmp(atts
[i
], "start") == 0) {
353 field
->start
= strtoul(atts
[i
+ 1], &p
, 0);
354 if (is_byte_offset(atts
[i
+ 1]))
356 } else if (strcmp(atts
[i
], "end") == 0) {
357 field
->end
= strtoul(atts
[i
+ 1], &p
, 0) - 1;
358 if (is_byte_offset(atts
[i
+ 1]))
360 } else if (strcmp(atts
[i
], "size") == 0) {
361 size
= strtoul(atts
[i
+ 1], &p
, 0);
362 if (is_byte_offset(atts
[i
+ 1]))
364 } else if (strcmp(atts
[i
], "type") == 0)
365 field
->type
= string_to_type(ctx
, atts
[i
+ 1]);
366 else if (strcmp(atts
[i
], "default") == 0) {
367 field
->has_default
= true;
368 field
->default_value
= strtoul(atts
[i
+ 1], &p
, 0);
369 } else if (strcmp(atts
[i
], "minus_one") == 0) {
370 assert(strcmp(atts
[i
+ 1], "true") == 0);
371 field
->minus_one
= true;
376 field
->end
= field
->start
+ size
- 1;
381 static struct v3d_value
*
382 create_value(struct parser_context
*ctx
, const char **atts
)
384 struct v3d_value
*value
= xzalloc(sizeof(*value
));
386 for (int i
= 0; atts
[i
]; i
+= 2) {
387 if (strcmp(atts
[i
], "name") == 0)
388 value
->name
= xstrdup(atts
[i
+ 1]);
389 else if (strcmp(atts
[i
], "value") == 0)
390 value
->value
= strtoul(atts
[i
+ 1], NULL
, 0);
397 create_and_append_field(struct parser_context
*ctx
,
400 if (ctx
->group
->nfields
== ctx
->group
->fields_size
) {
401 ctx
->group
->fields_size
= MAX2(ctx
->group
->fields_size
* 2, 2);
403 (struct v3d_field
**) realloc(ctx
->group
->fields
,
404 sizeof(ctx
->group
->fields
[0]) *
405 ctx
->group
->fields_size
);
408 ctx
->group
->fields
[ctx
->group
->nfields
++] = create_field(ctx
, atts
);
412 set_group_opcode(struct v3d_group
*group
, const char **atts
)
417 for (i
= 0; atts
[i
]; i
+= 2) {
418 if (strcmp(atts
[i
], "code") == 0)
419 group
->opcode
= strtoul(atts
[i
+ 1], &p
, 0);
425 ver_in_range(int ver
, int min_ver
, int max_ver
)
427 return ((min_ver
== 0 || ver
>= min_ver
) &&
428 (max_ver
== 0 || ver
<= max_ver
));
432 skip_if_ver_mismatch(struct parser_context
*ctx
, int min_ver
, int max_ver
)
434 if (!ctx
->parse_skip_depth
&& !ver_in_range(ctx
->devinfo
->ver
,
436 assert(ctx
->parse_depth
!= 0);
437 ctx
->parse_skip_depth
= ctx
->parse_depth
;
440 return ctx
->parse_skip_depth
;
444 start_element(void *data
, const char *element_name
, const char **atts
)
446 struct parser_context
*ctx
= data
;
448 const char *name
= NULL
;
449 const char *ver
= NULL
;
453 ctx
->loc
.line_number
= XML_GetCurrentLineNumber(ctx
->parser
);
455 for (i
= 0; atts
[i
]; i
+= 2) {
456 if (strcmp(atts
[i
], "name") == 0)
458 else if (strcmp(atts
[i
], "gen") == 0)
460 else if (strcmp(atts
[i
], "min_ver") == 0)
461 min_ver
= strtoul(atts
[i
+ 1], NULL
, 0);
462 else if (strcmp(atts
[i
], "max_ver") == 0)
463 max_ver
= strtoul(atts
[i
+ 1], NULL
, 0);
466 if (skip_if_ver_mismatch(ctx
, min_ver
, max_ver
))
469 if (strcmp(element_name
, "vcxml") == 0) {
471 fail(&ctx
->loc
, "no ver given");
473 /* Make sure that we picked an XML that matched our version.
475 assert(ver_in_range(ctx
->devinfo
->ver
, min_ver
, max_ver
));
478 int n
= sscanf(ver
, "%d.%d", &major
, &minor
);
480 fail(&ctx
->loc
, "invalid ver given: %s", ver
);
484 ctx
->spec
->ver
= major
* 10 + minor
;
485 } else if (strcmp(element_name
, "packet") == 0 ||
486 strcmp(element_name
, "struct") == 0) {
487 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
489 if (strcmp(element_name
, "packet") == 0)
490 set_group_opcode(ctx
->group
, atts
);
491 } else if (strcmp(element_name
, "register") == 0) {
492 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
493 get_register_offset(atts
, &ctx
->group
->register_offset
);
494 } else if (strcmp(element_name
, "group") == 0) {
495 struct v3d_group
*previous_group
= ctx
->group
;
496 while (previous_group
->next
)
497 previous_group
= previous_group
->next
;
499 struct v3d_group
*group
= create_group(ctx
, "", atts
,
501 previous_group
->next
= group
;
503 } else if (strcmp(element_name
, "field") == 0) {
504 create_and_append_field(ctx
, atts
);
505 } else if (strcmp(element_name
, "enum") == 0) {
506 ctx
->enoom
= create_enum(ctx
, name
, atts
);
507 } else if (strcmp(element_name
, "value") == 0) {
508 ctx
->values
[ctx
->nvalues
++] = create_value(ctx
, atts
);
509 assert(ctx
->nvalues
< ARRAY_SIZE(ctx
->values
));
517 field_offset_compare(const void *a
, const void *b
)
519 return ((*(const struct v3d_field
**)a
)->start
-
520 (*(const struct v3d_field
**)b
)->start
);
524 end_element(void *data
, const char *name
)
526 struct parser_context
*ctx
= data
;
527 struct v3d_spec
*spec
= ctx
->spec
;
531 if (ctx
->parse_skip_depth
) {
532 if (ctx
->parse_skip_depth
== ctx
->parse_depth
)
533 ctx
->parse_skip_depth
= 0;
537 if (strcmp(name
, "packet") == 0 ||
538 strcmp(name
, "struct") == 0 ||
539 strcmp(name
, "register") == 0) {
540 struct v3d_group
*group
= ctx
->group
;
542 ctx
->group
= ctx
->group
->parent
;
544 if (strcmp(name
, "packet") == 0) {
545 spec
->commands
[spec
->ncommands
++] = group
;
547 /* V3D packet XML has the packet contents with offsets
548 * starting from the first bit after the opcode, to
549 * match the spec. Shift the fields up now.
551 for (int i
= 0; i
< group
->nfields
; i
++) {
552 group
->fields
[i
]->start
+= 8;
553 group
->fields
[i
]->end
+= 8;
556 else if (strcmp(name
, "struct") == 0)
557 spec
->structs
[spec
->nstructs
++] = group
;
558 else if (strcmp(name
, "register") == 0)
559 spec
->registers
[spec
->nregisters
++] = group
;
561 /* Sort the fields in increasing offset order. The XML might
562 * be specified in any order, but we'll want to iterate from
565 qsort(group
->fields
, group
->nfields
, sizeof(*group
->fields
),
566 field_offset_compare
);
568 assert(spec
->ncommands
< ARRAY_SIZE(spec
->commands
));
569 assert(spec
->nstructs
< ARRAY_SIZE(spec
->structs
));
570 assert(spec
->nregisters
< ARRAY_SIZE(spec
->registers
));
571 } else if (strcmp(name
, "group") == 0) {
572 ctx
->group
= ctx
->group
->parent
;
573 } else if (strcmp(name
, "field") == 0) {
574 assert(ctx
->group
->nfields
> 0);
575 struct v3d_field
*field
= ctx
->group
->fields
[ctx
->group
->nfields
- 1];
576 size_t size
= ctx
->nvalues
* sizeof(ctx
->values
[0]);
577 field
->inline_enum
.values
= xzalloc(size
);
578 field
->inline_enum
.nvalues
= ctx
->nvalues
;
579 memcpy(field
->inline_enum
.values
, ctx
->values
, size
);
581 } else if (strcmp(name
, "enum") == 0) {
582 struct v3d_enum
*e
= ctx
->enoom
;
583 size_t size
= ctx
->nvalues
* sizeof(ctx
->values
[0]);
584 e
->values
= xzalloc(size
);
585 e
->nvalues
= ctx
->nvalues
;
586 memcpy(e
->values
, ctx
->values
, size
);
589 spec
->enums
[spec
->nenums
++] = e
;
594 character_data(void *data
, const XML_Char
*s
, int len
)
598 static uint32_t zlib_inflate(const void *compressed_data
,
599 uint32_t compressed_len
,
602 struct z_stream_s zstream
;
605 memset(&zstream
, 0, sizeof(zstream
));
607 zstream
.next_in
= (unsigned char *)compressed_data
;
608 zstream
.avail_in
= compressed_len
;
610 if (inflateInit(&zstream
) != Z_OK
)
614 zstream
.next_out
= out
;
615 zstream
.avail_out
= 4096;
618 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
624 inflateEnd(&zstream
);
628 if (zstream
.avail_out
)
631 out
= realloc(out
, 2*zstream
.total_out
);
633 inflateEnd(&zstream
);
637 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
638 zstream
.avail_out
= zstream
.total_out
;
641 inflateEnd(&zstream
);
643 return zstream
.total_out
;
647 v3d_spec_load(const struct v3d_device_info
*devinfo
)
649 struct parser_context ctx
;
651 uint8_t *text_data
= NULL
;
652 uint32_t text_offset
= 0, text_length
= 0, total_length
;
654 for (int i
= 0; i
< ARRAY_SIZE(genxml_files_table
); i
++) {
656 assert(genxml_files_table
[i
- 1].gen_10
<
657 genxml_files_table
[i
].gen_10
);
660 if (genxml_files_table
[i
].gen_10
<= devinfo
->ver
) {
661 text_offset
= genxml_files_table
[i
].offset
;
662 text_length
= genxml_files_table
[i
].length
;
666 if (text_length
== 0) {
667 fprintf(stderr
, "unable to find gen (%u) data\n", devinfo
->ver
);
671 memset(&ctx
, 0, sizeof ctx
);
672 ctx
.parser
= XML_ParserCreate(NULL
);
673 ctx
.devinfo
= devinfo
;
674 XML_SetUserData(ctx
.parser
, &ctx
);
675 if (ctx
.parser
== NULL
) {
676 fprintf(stderr
, "failed to create parser\n");
680 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
681 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
683 ctx
.spec
= xzalloc(sizeof(*ctx
.spec
));
685 total_length
= zlib_inflate(compress_genxmls
,
686 sizeof(compress_genxmls
),
687 (void **) &text_data
);
688 assert(text_offset
+ text_length
<= total_length
);
690 buf
= XML_GetBuffer(ctx
.parser
, text_length
);
691 memcpy(buf
, &text_data
[text_offset
], text_length
);
693 if (XML_ParseBuffer(ctx
.parser
, text_length
, true) == 0) {
695 "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
696 XML_GetCurrentLineNumber(ctx
.parser
),
697 XML_GetCurrentColumnNumber(ctx
.parser
),
698 XML_GetCurrentByteIndex(ctx
.parser
), text_length
,
699 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
700 XML_ParserFree(ctx
.parser
);
705 XML_ParserFree(ctx
.parser
);
712 v3d_spec_find_instruction(struct v3d_spec
*spec
, const uint8_t *p
)
716 for (int i
= 0; i
< spec
->ncommands
; i
++) {
717 struct v3d_group
*group
= spec
->commands
[i
];
719 if (opcode
!= group
->opcode
)
722 /* If there's a "sub-id" field, make sure that it matches the
723 * instruction being decoded.
725 struct v3d_field
*subid
= NULL
;
726 for (int j
= 0; j
< group
->nfields
; j
++) {
727 struct v3d_field
*field
= group
->fields
[j
];
728 if (strcmp(field
->name
, "sub-id") == 0) {
734 if (subid
&& (__gen_unpack_uint(p
, subid
->start
, subid
->end
) !=
735 subid
->default_value
)) {
745 /** Returns the size of a V3D packet. */
747 v3d_group_get_length(struct v3d_group
*group
)
750 for (int i
= 0; i
< group
->nfields
; i
++) {
751 struct v3d_field
*field
= group
->fields
[i
];
753 last_bit
= MAX2(last_bit
, field
->end
);
755 return last_bit
/ 8 + 1;
759 v3d_field_iterator_init(struct v3d_field_iterator
*iter
,
760 struct v3d_group
*group
,
763 memset(iter
, 0, sizeof(*iter
));
770 v3d_get_enum_name(struct v3d_enum
*e
, uint64_t value
)
772 for (int i
= 0; i
< e
->nvalues
; i
++) {
773 if (e
->values
[i
]->value
== value
) {
774 return e
->values
[i
]->name
;
781 iter_more_fields(const struct v3d_field_iterator
*iter
)
783 return iter
->field_iter
< iter
->group
->nfields
;
787 iter_group_offset_bits(const struct v3d_field_iterator
*iter
,
790 return iter
->group
->group_offset
+ (group_iter
*
791 iter
->group
->group_size
);
795 iter_more_groups(const struct v3d_field_iterator
*iter
)
797 if (iter
->group
->variable
) {
798 return iter_group_offset_bits(iter
, iter
->group_iter
+ 1) <
799 (v3d_group_get_length(iter
->group
) * 8);
801 return (iter
->group_iter
+ 1) < iter
->group
->group_count
||
802 iter
->group
->next
!= NULL
;
807 iter_advance_group(struct v3d_field_iterator
*iter
)
809 if (iter
->group
->variable
)
812 if ((iter
->group_iter
+ 1) < iter
->group
->group_count
) {
815 iter
->group
= iter
->group
->next
;
816 iter
->group_iter
= 0;
820 iter
->field_iter
= 0;
824 iter_advance_field(struct v3d_field_iterator
*iter
)
826 while (!iter_more_fields(iter
)) {
827 if (!iter_more_groups(iter
))
830 iter_advance_group(iter
);
833 iter
->field
= iter
->group
->fields
[iter
->field_iter
++];
834 if (iter
->field
->name
)
835 strncpy(iter
->name
, iter
->field
->name
, sizeof(iter
->name
));
837 memset(iter
->name
, 0, sizeof(iter
->name
));
838 iter
->offset
= iter_group_offset_bits(iter
, iter
->group_iter
) / 8 +
839 iter
->field
->start
/ 8;
840 iter
->struct_desc
= NULL
;
846 v3d_field_iterator_next(struct clif_dump
*clif
, struct v3d_field_iterator
*iter
)
848 if (!iter_advance_field(iter
))
851 const char *enum_name
= NULL
;
853 int group_member_offset
=
854 iter_group_offset_bits(iter
, iter
->group_iter
);
855 int s
= group_member_offset
+ iter
->field
->start
;
856 int e
= group_member_offset
+ iter
->field
->end
;
858 assert(!iter
->field
->minus_one
||
859 iter
->field
->type
.kind
== V3D_TYPE_INT
||
860 iter
->field
->type
.kind
== V3D_TYPE_UINT
);
862 switch (iter
->field
->type
.kind
) {
863 case V3D_TYPE_UNKNOWN
:
865 uint32_t value
= __gen_unpack_sint(iter
->p
, s
, e
);
866 if (iter
->field
->minus_one
)
868 snprintf(iter
->value
, sizeof(iter
->value
), "%d", value
);
869 enum_name
= v3d_get_enum_name(&iter
->field
->inline_enum
, value
);
872 case V3D_TYPE_UINT
: {
873 uint32_t value
= __gen_unpack_uint(iter
->p
, s
, e
);
874 if (iter
->field
->minus_one
)
876 if (strcmp(iter
->field
->name
, "Vec size") == 0 && value
== 0)
877 value
= 1 << (e
- s
);
878 snprintf(iter
->value
, sizeof(iter
->value
), "%u", value
);
879 enum_name
= v3d_get_enum_name(&iter
->field
->inline_enum
, value
);
883 snprintf(iter
->value
, sizeof(iter
->value
), "%s",
884 __gen_unpack_uint(iter
->p
, s
, e
) ?
885 "1 /* true */" : "0 /* false */");
888 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
889 __gen_unpack_float(iter
->p
, s
, e
));
893 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
894 __gen_unpack_f187(iter
->p
, s
, e
));
897 case V3D_TYPE_ADDRESS
: {
899 __gen_unpack_uint(iter
->p
, s
, e
) << (31 - (e
- s
));
900 struct clif_bo
*bo
= clif_lookup_bo(clif
, addr
);
902 snprintf(iter
->value
, sizeof(iter
->value
),
903 "[%s+0x%08x] /* 0x%08x */",
904 bo
->name
, addr
- bo
->offset
, addr
);
906 snprintf(iter
->value
, sizeof(iter
->value
),
907 "/* XXX: BO unknown */ 0x%08x", addr
);
909 snprintf(iter
->value
, sizeof(iter
->value
),
916 case V3D_TYPE_OFFSET
:
917 snprintf(iter
->value
, sizeof(iter
->value
), "0x%08"PRIx64
,
918 __gen_unpack_uint(iter
->p
, s
, e
) << (31 - (e
- s
)));
920 case V3D_TYPE_STRUCT
:
921 snprintf(iter
->value
, sizeof(iter
->value
), "<struct %s>",
922 iter
->field
->type
.v3d_struct
->name
);
924 v3d_spec_find_struct(iter
->group
->spec
,
925 iter
->field
->type
.v3d_struct
->name
);
927 case V3D_TYPE_SFIXED
:
928 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
929 __gen_unpack_sfixed(iter
->p
, s
, e
,
930 iter
->field
->type
.f
));
932 case V3D_TYPE_UFIXED
:
933 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
934 __gen_unpack_ufixed(iter
->p
, s
, e
,
935 iter
->field
->type
.f
));
939 case V3D_TYPE_ENUM
: {
940 uint32_t value
= __gen_unpack_uint(iter
->p
, s
, e
);
941 snprintf(iter
->value
, sizeof(iter
->value
), "%d", value
);
942 enum_name
= v3d_get_enum_name(iter
->field
->type
.v3d_enum
, value
);
947 if (strlen(iter
->group
->name
) == 0) {
948 int length
= strlen(iter
->name
);
949 snprintf(iter
->name
+ length
, sizeof(iter
->name
) - length
,
950 "[%i]", iter
->group_iter
);
954 int length
= strlen(iter
->value
);
955 snprintf(iter
->value
+ length
, sizeof(iter
->value
) - length
,
956 " /* %s */", enum_name
);
963 v3d_print_group(struct clif_dump
*clif
, struct v3d_group
*group
,
964 uint64_t offset
, const uint8_t *p
)
966 struct v3d_field_iterator iter
;
968 v3d_field_iterator_init(&iter
, group
, p
);
969 while (v3d_field_iterator_next(clif
, &iter
)) {
970 /* Clif parsing uses the packet name, and expects no
973 if (strcmp(iter
.field
->name
, "sub-id") == 0 ||
974 strcmp(iter
.field
->name
, "unused") == 0 ||
975 strcmp(iter
.field
->name
, "Pad") == 0)
979 fprintf(clif
->out
, " %s: %s\n",
980 iter
.name
, iter
.value
);
982 fprintf(clif
->out
, " /* %30s: */ %s\n",
983 iter
.name
, iter
.value
);
985 if (iter
.struct_desc
) {
986 uint64_t struct_offset
= offset
+ iter
.offset
;
987 v3d_print_group(clif
, iter
.struct_desc
,