2 * Copyright © 2016 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #include <util/macros.h>
34 #include <util/ralloc.h>
36 #include "gen_decoder.h"
38 #include "genxml/genX_xml.h"
40 #define XML_BUFFER_SIZE 4096
46 struct gen_group
*commands
[256];
48 struct gen_group
*structs
[256];
50 struct gen_group
*registers
[256];
52 struct gen_enum
*enums
[256];
60 struct parser_context
{
66 struct gen_group
*group
;
67 struct gen_enum
*enoom
;
70 struct gen_value
*values
[256];
72 struct gen_spec
*spec
;
76 gen_group_get_name(struct gen_group
*group
)
82 gen_group_get_opcode(struct gen_group
*group
)
88 gen_spec_find_struct(struct gen_spec
*spec
, const char *name
)
90 for (int i
= 0; i
< spec
->nstructs
; i
++)
91 if (strcmp(spec
->structs
[i
]->name
, name
) == 0)
92 return spec
->structs
[i
];
98 gen_spec_find_register(struct gen_spec
*spec
, uint32_t offset
)
100 for (int i
= 0; i
< spec
->nregisters
; i
++)
101 if (spec
->registers
[i
]->register_offset
== offset
)
102 return spec
->registers
[i
];
108 gen_spec_find_register_by_name(struct gen_spec
*spec
, const char *name
)
110 for (int i
= 0; i
< spec
->nregisters
; i
++) {
111 if (strcmp(spec
->registers
[i
]->name
, name
) == 0)
112 return spec
->registers
[i
];
119 gen_spec_find_enum(struct gen_spec
*spec
, const char *name
)
121 for (int i
= 0; i
< spec
->nenums
; i
++)
122 if (strcmp(spec
->enums
[i
]->name
, name
) == 0)
123 return spec
->enums
[i
];
129 gen_spec_get_gen(struct gen_spec
*spec
)
134 static void __attribute__((noreturn
))
135 fail(struct location
*loc
, const char *msg
, ...)
140 fprintf(stderr
, "%s:%d: error: ",
141 loc
->filename
, loc
->line_number
);
142 vfprintf(stderr
, msg
, ap
);
143 fprintf(stderr
, "\n");
149 fail_on_null(void *p
)
152 fprintf(stderr
, "aubinator: out of memory\n");
160 xstrdup(const char *s
)
162 return fail_on_null(strdup(s
));
174 return fail_on_null(zalloc(s
));
178 get_group_offset_count(const char **atts
, uint32_t *offset
, uint32_t *count
,
179 uint32_t *size
, bool *variable
)
184 for (i
= 0; atts
[i
]; i
+= 2) {
185 if (strcmp(atts
[i
], "count") == 0) {
186 *count
= strtoul(atts
[i
+ 1], &p
, 0);
189 } else if (strcmp(atts
[i
], "start") == 0) {
190 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
191 } else if (strcmp(atts
[i
], "size") == 0) {
192 *size
= strtoul(atts
[i
+ 1], &p
, 0);
198 static struct gen_group
*
199 create_group(struct parser_context
*ctx
,
202 struct gen_group
*parent
)
204 struct gen_group
*group
;
206 group
= xzalloc(sizeof(*group
));
208 group
->name
= xstrdup(name
);
210 group
->spec
= ctx
->spec
;
211 group
->group_offset
= 0;
212 group
->group_count
= 0;
213 group
->variable
= false;
216 group
->parent
= parent
;
217 get_group_offset_count(atts
,
218 &group
->group_offset
,
227 static struct gen_enum
*
228 create_enum(struct parser_context
*ctx
, const char *name
, const char **atts
)
232 e
= xzalloc(sizeof(*e
));
234 e
->name
= xstrdup(name
);
242 get_register_offset(const char **atts
, uint32_t *offset
)
247 for (i
= 0; atts
[i
]; i
+= 2) {
248 if (strcmp(atts
[i
], "num") == 0)
249 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
255 get_start_end_pos(int *start
, int *end
)
257 /* start value has to be mod with 32 as we need the relative
258 * start position in the first DWord. For the end position, add
259 * the length of the field to the start position to get the
260 * relative postion in the 64 bit address.
262 if (*end
- *start
> 32) {
263 int len
= *end
- *start
;
264 *start
= *start
% 32;
267 *start
= *start
% 32;
274 static inline uint64_t
275 mask(int start
, int end
)
279 v
= ~0ULL >> (63 - end
+ start
);
284 static inline uint64_t
285 field(uint64_t value
, int start
, int end
)
287 get_start_end_pos(&start
, &end
);
288 return (value
& mask(start
, end
)) >> (start
);
291 static inline uint64_t
292 field_address(uint64_t value
, int start
, int end
)
294 /* no need to right shift for address/offset */
295 get_start_end_pos(&start
, &end
);
296 return (value
& mask(start
, end
));
299 static struct gen_type
300 string_to_type(struct parser_context
*ctx
, const char *s
)
306 if (strcmp(s
, "int") == 0)
307 return (struct gen_type
) { .kind
= GEN_TYPE_INT
};
308 else if (strcmp(s
, "uint") == 0)
309 return (struct gen_type
) { .kind
= GEN_TYPE_UINT
};
310 else if (strcmp(s
, "bool") == 0)
311 return (struct gen_type
) { .kind
= GEN_TYPE_BOOL
};
312 else if (strcmp(s
, "float") == 0)
313 return (struct gen_type
) { .kind
= GEN_TYPE_FLOAT
};
314 else if (strcmp(s
, "address") == 0)
315 return (struct gen_type
) { .kind
= GEN_TYPE_ADDRESS
};
316 else if (strcmp(s
, "offset") == 0)
317 return (struct gen_type
) { .kind
= GEN_TYPE_OFFSET
};
318 else if (sscanf(s
, "u%d.%d", &i
, &f
) == 2)
319 return (struct gen_type
) { .kind
= GEN_TYPE_UFIXED
, .i
= i
, .f
= f
};
320 else if (sscanf(s
, "s%d.%d", &i
, &f
) == 2)
321 return (struct gen_type
) { .kind
= GEN_TYPE_SFIXED
, .i
= i
, .f
= f
};
322 else if (g
= gen_spec_find_struct(ctx
->spec
, s
), g
!= NULL
)
323 return (struct gen_type
) { .kind
= GEN_TYPE_STRUCT
, .gen_struct
= g
};
324 else if (e
= gen_spec_find_enum(ctx
->spec
, s
), e
!= NULL
)
325 return (struct gen_type
) { .kind
= GEN_TYPE_ENUM
, .gen_enum
= e
};
326 else if (strcmp(s
, "mbo") == 0)
327 return (struct gen_type
) { .kind
= GEN_TYPE_MBO
};
329 fail(&ctx
->loc
, "invalid type: %s", s
);
332 static struct gen_field
*
333 create_field(struct parser_context
*ctx
, const char **atts
)
335 struct gen_field
*field
;
339 field
= xzalloc(sizeof(*field
));
341 for (i
= 0; atts
[i
]; i
+= 2) {
342 if (strcmp(atts
[i
], "name") == 0)
343 field
->name
= xstrdup(atts
[i
+ 1]);
344 else if (strcmp(atts
[i
], "start") == 0)
345 field
->start
= strtoul(atts
[i
+ 1], &p
, 0);
346 else if (strcmp(atts
[i
], "end") == 0) {
347 field
->end
= strtoul(atts
[i
+ 1], &p
, 0);
348 } else if (strcmp(atts
[i
], "type") == 0)
349 field
->type
= string_to_type(ctx
, atts
[i
+ 1]);
350 else if (strcmp(atts
[i
], "default") == 0 &&
351 field
->start
>= 16 && field
->end
<= 31) {
352 field
->has_default
= true;
353 field
->default_value
= strtoul(atts
[i
+ 1], &p
, 0);
360 static struct gen_value
*
361 create_value(struct parser_context
*ctx
, const char **atts
)
363 struct gen_value
*value
= xzalloc(sizeof(*value
));
365 for (int i
= 0; atts
[i
]; i
+= 2) {
366 if (strcmp(atts
[i
], "name") == 0)
367 value
->name
= xstrdup(atts
[i
+ 1]);
368 else if (strcmp(atts
[i
], "value") == 0)
369 value
->value
= strtoul(atts
[i
+ 1], NULL
, 0);
376 create_and_append_field(struct parser_context
*ctx
,
379 if (ctx
->group
->nfields
== ctx
->group
->fields_size
) {
380 ctx
->group
->fields_size
= MAX2(ctx
->group
->fields_size
* 2, 2);
382 (struct gen_field
**) realloc(ctx
->group
->fields
,
383 sizeof(ctx
->group
->fields
[0]) *
384 ctx
->group
->fields_size
);
387 ctx
->group
->fields
[ctx
->group
->nfields
++] = create_field(ctx
, atts
);
391 start_element(void *data
, const char *element_name
, const char **atts
)
393 struct parser_context
*ctx
= data
;
395 const char *name
= NULL
;
396 const char *gen
= NULL
;
398 ctx
->loc
.line_number
= XML_GetCurrentLineNumber(ctx
->parser
);
400 for (i
= 0; atts
[i
]; i
+= 2) {
401 if (strcmp(atts
[i
], "name") == 0)
403 else if (strcmp(atts
[i
], "gen") == 0)
407 if (strcmp(element_name
, "genxml") == 0) {
409 fail(&ctx
->loc
, "no platform name given");
411 fail(&ctx
->loc
, "no gen given");
413 ctx
->platform
= xstrdup(name
);
415 int n
= sscanf(gen
, "%d.%d", &major
, &minor
);
417 fail(&ctx
->loc
, "invalid gen given: %s", gen
);
421 ctx
->spec
->gen
= gen_make_gen(major
, minor
);
422 } else if (strcmp(element_name
, "instruction") == 0 ||
423 strcmp(element_name
, "struct") == 0) {
424 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
425 } else if (strcmp(element_name
, "register") == 0) {
426 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
427 get_register_offset(atts
, &ctx
->group
->register_offset
);
428 } else if (strcmp(element_name
, "group") == 0) {
429 struct gen_group
*previous_group
= ctx
->group
;
430 while (previous_group
->next
)
431 previous_group
= previous_group
->next
;
433 struct gen_group
*group
= create_group(ctx
, "", atts
, ctx
->group
);
434 previous_group
->next
= group
;
436 } else if (strcmp(element_name
, "field") == 0) {
437 create_and_append_field(ctx
, atts
);
438 } else if (strcmp(element_name
, "enum") == 0) {
439 ctx
->enoom
= create_enum(ctx
, name
, atts
);
440 } else if (strcmp(element_name
, "value") == 0) {
441 ctx
->values
[ctx
->nvalues
++] = create_value(ctx
, atts
);
442 assert(ctx
->nvalues
< ARRAY_SIZE(ctx
->values
));
448 end_element(void *data
, const char *name
)
450 struct parser_context
*ctx
= data
;
451 struct gen_spec
*spec
= ctx
->spec
;
453 if (strcmp(name
, "instruction") == 0 ||
454 strcmp(name
, "struct") == 0 ||
455 strcmp(name
, "register") == 0) {
456 struct gen_group
*group
= ctx
->group
;
458 ctx
->group
= ctx
->group
->parent
;
460 for (int i
= 0; i
< group
->nfields
; i
++) {
461 if (group
->fields
[i
]->start
>= 16 &&
462 group
->fields
[i
]->end
<= 31 &&
463 group
->fields
[i
]->has_default
) {
464 group
->opcode_mask
|=
465 mask(group
->fields
[i
]->start
% 32, group
->fields
[i
]->end
% 32);
467 group
->fields
[i
]->default_value
<< group
->fields
[i
]->start
;
471 if (strcmp(name
, "instruction") == 0)
472 spec
->commands
[spec
->ncommands
++] = group
;
473 else if (strcmp(name
, "struct") == 0)
474 spec
->structs
[spec
->nstructs
++] = group
;
475 else if (strcmp(name
, "register") == 0)
476 spec
->registers
[spec
->nregisters
++] = group
;
478 assert(spec
->ncommands
< ARRAY_SIZE(spec
->commands
));
479 assert(spec
->nstructs
< ARRAY_SIZE(spec
->structs
));
480 assert(spec
->nregisters
< ARRAY_SIZE(spec
->registers
));
481 } else if (strcmp(name
, "group") == 0) {
482 ctx
->group
= ctx
->group
->parent
;
483 } else if (strcmp(name
, "field") == 0) {
484 assert(ctx
->group
->nfields
> 0);
485 struct gen_field
*field
= ctx
->group
->fields
[ctx
->group
->nfields
- 1];
486 size_t size
= ctx
->nvalues
* sizeof(ctx
->values
[0]);
487 field
->inline_enum
.values
= xzalloc(size
);
488 field
->inline_enum
.nvalues
= ctx
->nvalues
;
489 memcpy(field
->inline_enum
.values
, ctx
->values
, size
);
491 } else if (strcmp(name
, "enum") == 0) {
492 struct gen_enum
*e
= ctx
->enoom
;
493 size_t size
= ctx
->nvalues
* sizeof(ctx
->values
[0]);
494 e
->values
= xzalloc(size
);
495 e
->nvalues
= ctx
->nvalues
;
496 memcpy(e
->values
, ctx
->values
, size
);
499 spec
->enums
[spec
->nenums
++] = e
;
504 character_data(void *data
, const XML_Char
*s
, int len
)
509 devinfo_to_gen(const struct gen_device_info
*devinfo
)
511 int value
= 10 * devinfo
->gen
;
513 if (devinfo
->is_baytrail
|| devinfo
->is_haswell
)
519 static uint32_t zlib_inflate(const void *compressed_data
,
520 uint32_t compressed_len
,
523 struct z_stream_s zstream
;
526 memset(&zstream
, 0, sizeof(zstream
));
528 zstream
.next_in
= (unsigned char *)compressed_data
;
529 zstream
.avail_in
= compressed_len
;
531 if (inflateInit(&zstream
) != Z_OK
)
535 zstream
.next_out
= out
;
536 zstream
.avail_out
= 4096;
539 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
545 inflateEnd(&zstream
);
549 if (zstream
.avail_out
)
552 out
= realloc(out
, 2*zstream
.total_out
);
554 inflateEnd(&zstream
);
558 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
559 zstream
.avail_out
= zstream
.total_out
;
562 inflateEnd(&zstream
);
564 return zstream
.total_out
;
568 gen_spec_load(const struct gen_device_info
*devinfo
)
570 struct parser_context ctx
;
572 uint8_t *text_data
= NULL
;
573 uint32_t text_offset
= 0, text_length
= 0, total_length
;
574 uint32_t gen_10
= devinfo_to_gen(devinfo
);
576 for (int i
= 0; i
< ARRAY_SIZE(genxml_files_table
); i
++) {
577 if (genxml_files_table
[i
].gen_10
== gen_10
) {
578 text_offset
= genxml_files_table
[i
].offset
;
579 text_length
= genxml_files_table
[i
].length
;
584 if (text_length
== 0) {
585 fprintf(stderr
, "unable to find gen (%u) data\n", gen_10
);
589 memset(&ctx
, 0, sizeof ctx
);
590 ctx
.parser
= XML_ParserCreate(NULL
);
591 XML_SetUserData(ctx
.parser
, &ctx
);
592 if (ctx
.parser
== NULL
) {
593 fprintf(stderr
, "failed to create parser\n");
597 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
598 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
600 ctx
.spec
= xzalloc(sizeof(*ctx
.spec
));
602 total_length
= zlib_inflate(compress_genxmls
,
603 sizeof(compress_genxmls
),
604 (void **) &text_data
);
605 assert(text_offset
+ text_length
<= total_length
);
607 buf
= XML_GetBuffer(ctx
.parser
, text_length
);
608 memcpy(buf
, &text_data
[text_offset
], text_length
);
610 if (XML_ParseBuffer(ctx
.parser
, text_length
, true) == 0) {
612 "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
613 XML_GetCurrentLineNumber(ctx
.parser
),
614 XML_GetCurrentColumnNumber(ctx
.parser
),
615 XML_GetCurrentByteIndex(ctx
.parser
), text_length
,
616 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
617 XML_ParserFree(ctx
.parser
);
622 XML_ParserFree(ctx
.parser
);
629 gen_spec_load_from_path(const struct gen_device_info
*devinfo
,
632 struct parser_context ctx
;
633 size_t len
, filename_len
= strlen(path
) + 20;
634 char *filename
= malloc(filename_len
);
638 len
= snprintf(filename
, filename_len
, "%s/gen%i.xml",
639 path
, devinfo_to_gen(devinfo
));
640 assert(len
< filename_len
);
642 input
= fopen(filename
, "r");
644 fprintf(stderr
, "failed to open xml description\n");
649 memset(&ctx
, 0, sizeof ctx
);
650 ctx
.parser
= XML_ParserCreate(NULL
);
651 XML_SetUserData(ctx
.parser
, &ctx
);
652 if (ctx
.parser
== NULL
) {
653 fprintf(stderr
, "failed to create parser\n");
659 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
660 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
661 ctx
.loc
.filename
= filename
;
662 ctx
.spec
= xzalloc(sizeof(*ctx
.spec
));
665 buf
= XML_GetBuffer(ctx
.parser
, XML_BUFFER_SIZE
);
666 len
= fread(buf
, 1, XML_BUFFER_SIZE
, input
);
668 fprintf(stderr
, "fread: %m\n");
673 if (XML_ParseBuffer(ctx
.parser
, len
, len
== 0) == 0) {
675 "Error parsing XML at line %ld col %ld: %s\n",
676 XML_GetCurrentLineNumber(ctx
.parser
),
677 XML_GetCurrentColumnNumber(ctx
.parser
),
678 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
686 XML_ParserFree(ctx
.parser
);
695 gen_spec_find_instruction(struct gen_spec
*spec
, const uint32_t *p
)
697 for (int i
= 0; i
< spec
->ncommands
; i
++) {
698 uint32_t opcode
= *p
& spec
->commands
[i
]->opcode_mask
;
699 if (opcode
== spec
->commands
[i
]->opcode
)
700 return spec
->commands
[i
];
707 gen_group_get_length(struct gen_group
*group
, const uint32_t *p
)
710 uint32_t type
= field(h
, 29, 31);
714 uint32_t opcode
= field(h
, 23, 28);
718 return field(h
, 0, 7) + 2;
723 return field(h
, 0, 7) + 2;
726 case 3: /* Render */ {
727 uint32_t subtype
= field(h
, 27, 28);
728 uint32_t opcode
= field(h
, 24, 26);
729 uint16_t whole_opcode
= field(h
, 16, 31);
732 if (whole_opcode
== 0x6104 /* PIPELINE_SELECT_965 */)
735 return field(h
, 0, 7) + 2;
745 return field(h
, 0, 7) + 2;
747 return field(h
, 0, 15) + 2;
752 if (whole_opcode
== 0x780b)
755 return field(h
, 0, 7) + 2;
766 gen_field_iterator_init(struct gen_field_iterator
*iter
,
767 struct gen_group
*group
,
771 memset(iter
, 0, sizeof(*iter
));
775 iter
->print_colors
= print_colors
;
779 gen_get_enum_name(struct gen_enum
*e
, uint64_t value
)
781 for (int i
= 0; i
< e
->nvalues
; i
++) {
782 if (e
->values
[i
]->value
== value
) {
783 return e
->values
[i
]->name
;
790 iter_more_fields(const struct gen_field_iterator
*iter
)
792 return iter
->field_iter
< iter
->group
->nfields
;
796 iter_group_offset_bits(const struct gen_field_iterator
*iter
,
799 return iter
->group
->group_offset
+ (group_iter
* iter
->group
->group_size
);
803 iter_more_groups(const struct gen_field_iterator
*iter
)
805 if (iter
->group
->variable
) {
806 return iter_group_offset_bits(iter
, iter
->group_iter
+ 1) <
807 (gen_group_get_length(iter
->group
, iter
->p
) * 32);
809 return (iter
->group_iter
+ 1) < iter
->group
->group_count
||
810 iter
->group
->next
!= NULL
;
815 iter_advance_group(struct gen_field_iterator
*iter
)
817 if (iter
->group
->variable
)
820 if ((iter
->group_iter
+ 1) < iter
->group
->group_count
) {
823 iter
->group
= iter
->group
->next
;
824 iter
->group_iter
= 0;
828 iter
->field_iter
= 0;
832 iter_advance_field(struct gen_field_iterator
*iter
)
834 while (!iter_more_fields(iter
)) {
835 if (!iter_more_groups(iter
))
838 iter_advance_group(iter
);
841 iter
->field
= iter
->group
->fields
[iter
->field_iter
++];
842 if (iter
->field
->name
)
843 strncpy(iter
->name
, iter
->field
->name
, sizeof(iter
->name
));
845 memset(iter
->name
, 0, sizeof(iter
->name
));
847 int group_member_offset
= iter_group_offset_bits(iter
, iter
->group_iter
);
849 iter
->start
= group_member_offset
+ iter
->field
->start
;
850 iter
->end
= group_member_offset
+ iter
->field
->end
;
851 iter
->dword
= iter
->start
/ 32;
852 iter
->struct_desc
= NULL
;
858 gen_field_iterator_next(struct gen_field_iterator
*iter
)
865 if (!iter_advance_field(iter
))
868 if ((iter
->end
- iter
->start
) > 32)
869 v
.qw
= ((uint64_t) iter
->p
[iter
->dword
+1] << 32) | iter
->p
[iter
->dword
];
871 v
.qw
= iter
->p
[iter
->dword
];
873 const char *enum_name
= NULL
;
875 switch (iter
->field
->type
.kind
) {
876 case GEN_TYPE_UNKNOWN
:
878 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
879 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRId64
, value
);
880 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, value
);
883 case GEN_TYPE_UINT
: {
884 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
885 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRIu64
, value
);
886 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, value
);
889 case GEN_TYPE_BOOL
: {
890 const char *true_string
=
891 iter
->print_colors
? "\e[0;35mtrue\e[0m" : "true";
892 snprintf(iter
->value
, sizeof(iter
->value
), "%s",
893 field(v
.qw
, iter
->start
, iter
->end
) ?
894 true_string
: "false");
898 snprintf(iter
->value
, sizeof(iter
->value
), "%f", v
.f
);
900 case GEN_TYPE_ADDRESS
:
901 case GEN_TYPE_OFFSET
:
902 snprintf(iter
->value
, sizeof(iter
->value
), "0x%08"PRIx64
,
903 field_address(v
.qw
, iter
->start
, iter
->end
));
905 case GEN_TYPE_STRUCT
:
906 snprintf(iter
->value
, sizeof(iter
->value
), "<struct %s>",
907 iter
->field
->type
.gen_struct
->name
);
909 gen_spec_find_struct(iter
->group
->spec
,
910 iter
->field
->type
.gen_struct
->name
);
912 case GEN_TYPE_UFIXED
:
913 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
914 (float) field(v
.qw
, iter
->start
, iter
->end
) /
915 (1 << iter
->field
->type
.f
));
917 case GEN_TYPE_SFIXED
:
918 /* FIXME: Sign extend extracted field. */
919 snprintf(iter
->value
, sizeof(iter
->value
), "%s", "foo");
923 case GEN_TYPE_ENUM
: {
924 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
925 snprintf(iter
->value
, sizeof(iter
->value
),
927 enum_name
= gen_get_enum_name(iter
->field
->type
.gen_enum
, value
);
932 if (strlen(iter
->group
->name
) == 0) {
933 int length
= strlen(iter
->name
);
934 snprintf(iter
->name
+ length
, sizeof(iter
->name
) - length
,
935 "[%i]", iter
->group_iter
);
939 int length
= strlen(iter
->value
);
940 snprintf(iter
->value
+ length
, sizeof(iter
->value
) - length
,
948 print_dword_header(FILE *outfile
,
949 struct gen_field_iterator
*iter
, uint64_t offset
)
951 fprintf(outfile
, "0x%08"PRIx64
": 0x%08x : Dword %d\n",
952 offset
+ 4 * iter
->dword
, iter
->p
[iter
->dword
], iter
->dword
);
956 is_header_field(struct gen_group
*group
, struct gen_field
*field
)
960 if (field
->start
>= 32)
963 bits
= (1U << (field
->end
- field
->start
+ 1)) - 1;
964 bits
<<= field
->start
;
966 return (group
->opcode_mask
& bits
) != 0;
970 gen_print_group(FILE *outfile
, struct gen_group
*group
,
971 uint64_t offset
, const uint32_t *p
, bool color
)
973 struct gen_field_iterator iter
;
976 gen_field_iterator_init(&iter
, group
, p
, color
);
977 while (gen_field_iterator_next(&iter
)) {
978 if (last_dword
!= iter
.dword
) {
979 print_dword_header(outfile
, &iter
, offset
);
980 last_dword
= iter
.dword
;
982 if (!is_header_field(group
, iter
.field
)) {
983 fprintf(outfile
, " %s: %s\n", iter
.name
, iter
.value
);
984 if (iter
.struct_desc
) {
985 uint64_t struct_offset
= offset
+ 4 * iter
.dword
;
986 gen_print_group(outfile
, iter
.struct_desc
, struct_offset
,
987 &p
[iter
.dword
], color
);