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
41 #define MAX_VALUE_ITEMS 128
48 struct parser_context
{
53 struct gen_group
*group
;
54 struct gen_enum
*enoom
;
56 int n_values
, n_allocated_values
;
57 struct gen_value
**values
;
59 struct gen_field
*last_field
;
61 struct gen_spec
*spec
;
65 gen_group_get_name(struct gen_group
*group
)
71 gen_group_get_opcode(struct gen_group
*group
)
77 gen_spec_find_struct(struct gen_spec
*spec
, const char *name
)
79 struct hash_entry
*entry
= _mesa_hash_table_search(spec
->structs
,
81 return entry
? entry
->data
: NULL
;
85 gen_spec_find_register(struct gen_spec
*spec
, uint32_t offset
)
87 struct hash_entry
*entry
=
88 _mesa_hash_table_search(spec
->registers_by_offset
,
89 (void *) (uintptr_t) offset
);
90 return entry
? entry
->data
: NULL
;
94 gen_spec_find_register_by_name(struct gen_spec
*spec
, const char *name
)
96 struct hash_entry
*entry
=
97 _mesa_hash_table_search(spec
->registers_by_name
, name
);
98 return entry
? entry
->data
: NULL
;
102 gen_spec_find_enum(struct gen_spec
*spec
, const char *name
)
104 struct hash_entry
*entry
= _mesa_hash_table_search(spec
->enums
,
106 return entry
? entry
->data
: NULL
;
110 gen_spec_get_gen(struct gen_spec
*spec
)
115 static void __attribute__((noreturn
))
116 fail(struct location
*loc
, const char *msg
, ...)
121 fprintf(stderr
, "%s:%d: error: ",
122 loc
->filename
, loc
->line_number
);
123 vfprintf(stderr
, msg
, ap
);
124 fprintf(stderr
, "\n");
130 get_group_offset_count(const char **atts
, uint32_t *offset
, uint32_t *count
,
131 uint32_t *size
, bool *variable
)
133 for (int i
= 0; atts
[i
]; i
+= 2) {
136 if (strcmp(atts
[i
], "count") == 0) {
137 *count
= strtoul(atts
[i
+ 1], &p
, 0);
140 } else if (strcmp(atts
[i
], "start") == 0) {
141 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
142 } else if (strcmp(atts
[i
], "size") == 0) {
143 *size
= strtoul(atts
[i
+ 1], &p
, 0);
149 static struct gen_group
*
150 create_group(struct parser_context
*ctx
,
153 struct gen_group
*parent
)
155 struct gen_group
*group
;
157 group
= rzalloc(ctx
->spec
, struct gen_group
);
159 group
->name
= ralloc_strdup(group
, name
);
161 group
->spec
= ctx
->spec
;
162 group
->variable
= false;
164 for (int i
= 0; atts
[i
]; i
+= 2) {
166 if (strcmp(atts
[i
], "length") == 0) {
167 group
->dw_length
= strtoul(atts
[i
+ 1], &p
, 0);
172 group
->parent
= parent
;
173 get_group_offset_count(atts
,
174 &group
->group_offset
,
183 static struct gen_enum
*
184 create_enum(struct parser_context
*ctx
, const char *name
, const char **atts
)
188 e
= rzalloc(ctx
->spec
, struct gen_enum
);
190 e
->name
= ralloc_strdup(e
, name
);
196 get_register_offset(const char **atts
, uint32_t *offset
)
198 for (int i
= 0; atts
[i
]; i
+= 2) {
201 if (strcmp(atts
[i
], "num") == 0)
202 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
208 get_start_end_pos(int *start
, int *end
)
210 /* start value has to be mod with 32 as we need the relative
211 * start position in the first DWord. For the end position, add
212 * the length of the field to the start position to get the
213 * relative postion in the 64 bit address.
215 if (*end
- *start
> 32) {
216 int len
= *end
- *start
;
217 *start
= *start
% 32;
220 *start
= *start
% 32;
227 static inline uint64_t
228 mask(int start
, int end
)
232 v
= ~0ULL >> (63 - end
+ start
);
237 static inline uint64_t
238 field(uint64_t value
, int start
, int end
)
240 get_start_end_pos(&start
, &end
);
241 return (value
& mask(start
, end
)) >> (start
);
244 static inline uint64_t
245 field_address(uint64_t value
, int start
, int end
)
247 /* no need to right shift for address/offset */
248 get_start_end_pos(&start
, &end
);
249 return (value
& mask(start
, end
));
252 static struct gen_type
253 string_to_type(struct parser_context
*ctx
, const char *s
)
259 if (strcmp(s
, "int") == 0)
260 return (struct gen_type
) { .kind
= GEN_TYPE_INT
};
261 else if (strcmp(s
, "uint") == 0)
262 return (struct gen_type
) { .kind
= GEN_TYPE_UINT
};
263 else if (strcmp(s
, "bool") == 0)
264 return (struct gen_type
) { .kind
= GEN_TYPE_BOOL
};
265 else if (strcmp(s
, "float") == 0)
266 return (struct gen_type
) { .kind
= GEN_TYPE_FLOAT
};
267 else if (strcmp(s
, "address") == 0)
268 return (struct gen_type
) { .kind
= GEN_TYPE_ADDRESS
};
269 else if (strcmp(s
, "offset") == 0)
270 return (struct gen_type
) { .kind
= GEN_TYPE_OFFSET
};
271 else if (sscanf(s
, "u%d.%d", &i
, &f
) == 2)
272 return (struct gen_type
) { .kind
= GEN_TYPE_UFIXED
, .i
= i
, .f
= f
};
273 else if (sscanf(s
, "s%d.%d", &i
, &f
) == 2)
274 return (struct gen_type
) { .kind
= GEN_TYPE_SFIXED
, .i
= i
, .f
= f
};
275 else if (g
= gen_spec_find_struct(ctx
->spec
, s
), g
!= NULL
)
276 return (struct gen_type
) { .kind
= GEN_TYPE_STRUCT
, .gen_struct
= g
};
277 else if (e
= gen_spec_find_enum(ctx
->spec
, s
), e
!= NULL
)
278 return (struct gen_type
) { .kind
= GEN_TYPE_ENUM
, .gen_enum
= e
};
279 else if (strcmp(s
, "mbo") == 0)
280 return (struct gen_type
) { .kind
= GEN_TYPE_MBO
};
282 fail(&ctx
->loc
, "invalid type: %s", s
);
285 static struct gen_field
*
286 create_field(struct parser_context
*ctx
, const char **atts
)
288 struct gen_field
*field
;
290 field
= rzalloc(ctx
->group
, struct gen_field
);
291 field
->parent
= ctx
->group
;
293 for (int i
= 0; atts
[i
]; i
+= 2) {
296 if (strcmp(atts
[i
], "name") == 0)
297 field
->name
= ralloc_strdup(field
, atts
[i
+ 1]);
298 else if (strcmp(atts
[i
], "start") == 0)
299 field
->start
= strtoul(atts
[i
+ 1], &p
, 0);
300 else if (strcmp(atts
[i
], "end") == 0) {
301 field
->end
= strtoul(atts
[i
+ 1], &p
, 0);
302 } else if (strcmp(atts
[i
], "type") == 0)
303 field
->type
= string_to_type(ctx
, atts
[i
+ 1]);
304 else if (strcmp(atts
[i
], "default") == 0 &&
305 field
->start
>= 16 && field
->end
<= 31) {
306 field
->has_default
= true;
307 field
->default_value
= strtoul(atts
[i
+ 1], &p
, 0);
314 static struct gen_value
*
315 create_value(struct parser_context
*ctx
, const char **atts
)
317 struct gen_value
*value
= rzalloc(ctx
->values
, struct gen_value
);
319 for (int i
= 0; atts
[i
]; i
+= 2) {
320 if (strcmp(atts
[i
], "name") == 0)
321 value
->name
= ralloc_strdup(value
, atts
[i
+ 1]);
322 else if (strcmp(atts
[i
], "value") == 0)
323 value
->value
= strtoul(atts
[i
+ 1], NULL
, 0);
329 static struct gen_field
*
330 create_and_append_field(struct parser_context
*ctx
,
333 struct gen_field
*field
= create_field(ctx
, atts
);
334 struct gen_field
*prev
= NULL
, *list
= ctx
->group
->fields
;
336 while (list
&& field
->start
> list
->start
) {
343 ctx
->group
->fields
= field
;
351 start_element(void *data
, const char *element_name
, const char **atts
)
353 struct parser_context
*ctx
= data
;
354 const char *name
= NULL
;
355 const char *gen
= NULL
;
357 ctx
->loc
.line_number
= XML_GetCurrentLineNumber(ctx
->parser
);
359 for (int i
= 0; atts
[i
]; i
+= 2) {
360 if (strcmp(atts
[i
], "name") == 0)
362 else if (strcmp(atts
[i
], "gen") == 0)
366 if (strcmp(element_name
, "genxml") == 0) {
368 fail(&ctx
->loc
, "no platform name given");
370 fail(&ctx
->loc
, "no gen given");
373 int n
= sscanf(gen
, "%d.%d", &major
, &minor
);
375 fail(&ctx
->loc
, "invalid gen given: %s", gen
);
379 ctx
->spec
->gen
= gen_make_gen(major
, minor
);
380 } else if (strcmp(element_name
, "instruction") == 0 ||
381 strcmp(element_name
, "struct") == 0) {
382 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
383 } else if (strcmp(element_name
, "register") == 0) {
384 ctx
->group
= create_group(ctx
, name
, atts
, NULL
);
385 get_register_offset(atts
, &ctx
->group
->register_offset
);
386 } else if (strcmp(element_name
, "group") == 0) {
387 struct gen_group
*previous_group
= ctx
->group
;
388 while (previous_group
->next
)
389 previous_group
= previous_group
->next
;
391 struct gen_group
*group
= create_group(ctx
, "", atts
, ctx
->group
);
392 previous_group
->next
= group
;
394 } else if (strcmp(element_name
, "field") == 0) {
395 ctx
->last_field
= create_and_append_field(ctx
, atts
);
396 } else if (strcmp(element_name
, "enum") == 0) {
397 ctx
->enoom
= create_enum(ctx
, name
, atts
);
398 } else if (strcmp(element_name
, "value") == 0) {
399 if (ctx
->n_values
>= ctx
->n_allocated_values
) {
400 ctx
->n_allocated_values
= MAX2(2, ctx
->n_allocated_values
* 2);
401 ctx
->values
= reralloc_array_size(ctx
->spec
, ctx
->values
,
402 sizeof(struct gen_value
*),
403 ctx
->n_allocated_values
);
405 assert(ctx
->n_values
< ctx
->n_allocated_values
);
406 ctx
->values
[ctx
->n_values
++] = create_value(ctx
, atts
);
412 end_element(void *data
, const char *name
)
414 struct parser_context
*ctx
= data
;
415 struct gen_spec
*spec
= ctx
->spec
;
417 if (strcmp(name
, "instruction") == 0 ||
418 strcmp(name
, "struct") == 0 ||
419 strcmp(name
, "register") == 0) {
420 struct gen_group
*group
= ctx
->group
;
421 struct gen_field
*list
= group
->fields
;
423 ctx
->group
= ctx
->group
->parent
;
425 while (list
&& list
->end
<= 31) {
426 if (list
->start
>= 16 && list
->has_default
) {
427 group
->opcode_mask
|=
428 mask(list
->start
% 32, list
->end
% 32);
429 group
->opcode
|= list
->default_value
<< list
->start
;
434 if (strcmp(name
, "instruction") == 0)
435 _mesa_hash_table_insert(spec
->commands
, group
->name
, group
);
436 else if (strcmp(name
, "struct") == 0)
437 _mesa_hash_table_insert(spec
->structs
, group
->name
, group
);
438 else if (strcmp(name
, "register") == 0) {
439 _mesa_hash_table_insert(spec
->registers_by_name
, group
->name
, group
);
440 _mesa_hash_table_insert(spec
->registers_by_offset
,
441 (void *) (uintptr_t) group
->register_offset
,
444 } else if (strcmp(name
, "group") == 0) {
445 ctx
->group
= ctx
->group
->parent
;
446 } else if (strcmp(name
, "field") == 0) {
447 struct gen_field
*field
= ctx
->last_field
;
448 ctx
->last_field
= NULL
;
449 field
->inline_enum
.values
= ctx
->values
;
450 field
->inline_enum
.nvalues
= ctx
->n_values
;
451 ctx
->values
= ralloc_array(ctx
->spec
, struct gen_value
*, ctx
->n_allocated_values
= 2);
453 } else if (strcmp(name
, "enum") == 0) {
454 struct gen_enum
*e
= ctx
->enoom
;
455 e
->values
= ctx
->values
;
456 e
->nvalues
= ctx
->n_values
;
457 ctx
->values
= ralloc_array(ctx
->spec
, struct gen_value
*, ctx
->n_allocated_values
= 2);
460 _mesa_hash_table_insert(spec
->enums
, e
->name
, e
);
465 character_data(void *data
, const XML_Char
*s
, int len
)
470 devinfo_to_gen(const struct gen_device_info
*devinfo
)
472 int value
= 10 * devinfo
->gen
;
474 if (devinfo
->is_baytrail
|| devinfo
->is_haswell
)
480 static uint32_t zlib_inflate(const void *compressed_data
,
481 uint32_t compressed_len
,
484 struct z_stream_s zstream
;
487 memset(&zstream
, 0, sizeof(zstream
));
489 zstream
.next_in
= (unsigned char *)compressed_data
;
490 zstream
.avail_in
= compressed_len
;
492 if (inflateInit(&zstream
) != Z_OK
)
496 zstream
.next_out
= out
;
497 zstream
.avail_out
= 4096;
500 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
506 inflateEnd(&zstream
);
510 if (zstream
.avail_out
)
513 out
= realloc(out
, 2*zstream
.total_out
);
515 inflateEnd(&zstream
);
519 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
520 zstream
.avail_out
= zstream
.total_out
;
523 inflateEnd(&zstream
);
525 return zstream
.total_out
;
528 static uint32_t _hash_uint32(const void *key
)
530 return (uint32_t) (uintptr_t) key
;
534 gen_spec_load(const struct gen_device_info
*devinfo
)
536 struct parser_context ctx
;
538 uint8_t *text_data
= NULL
;
539 uint32_t text_offset
= 0, text_length
= 0, total_length
;
540 uint32_t gen_10
= devinfo_to_gen(devinfo
);
542 for (int i
= 0; i
< ARRAY_SIZE(genxml_files_table
); i
++) {
543 if (genxml_files_table
[i
].gen_10
== gen_10
) {
544 text_offset
= genxml_files_table
[i
].offset
;
545 text_length
= genxml_files_table
[i
].length
;
550 if (text_length
== 0) {
551 fprintf(stderr
, "unable to find gen (%u) data\n", gen_10
);
555 memset(&ctx
, 0, sizeof ctx
);
556 ctx
.parser
= XML_ParserCreate(NULL
);
557 XML_SetUserData(ctx
.parser
, &ctx
);
558 if (ctx
.parser
== NULL
) {
559 fprintf(stderr
, "failed to create parser\n");
563 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
564 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
566 ctx
.spec
= rzalloc(NULL
, struct gen_spec
);
569 _mesa_hash_table_create(ctx
.spec
, _mesa_hash_string
, _mesa_key_string_equal
);
571 _mesa_hash_table_create(ctx
.spec
, _mesa_hash_string
, _mesa_key_string_equal
);
572 ctx
.spec
->registers_by_name
=
573 _mesa_hash_table_create(ctx
.spec
, _mesa_hash_string
, _mesa_key_string_equal
);
574 ctx
.spec
->registers_by_offset
=
575 _mesa_hash_table_create(ctx
.spec
, _hash_uint32
, _mesa_key_pointer_equal
);
577 _mesa_hash_table_create(ctx
.spec
, _mesa_hash_string
, _mesa_key_string_equal
);
579 total_length
= zlib_inflate(compress_genxmls
,
580 sizeof(compress_genxmls
),
581 (void **) &text_data
);
582 assert(text_offset
+ text_length
<= total_length
);
584 buf
= XML_GetBuffer(ctx
.parser
, text_length
);
585 memcpy(buf
, &text_data
[text_offset
], text_length
);
587 if (XML_ParseBuffer(ctx
.parser
, text_length
, true) == 0) {
589 "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
590 XML_GetCurrentLineNumber(ctx
.parser
),
591 XML_GetCurrentColumnNumber(ctx
.parser
),
592 XML_GetCurrentByteIndex(ctx
.parser
), text_length
,
593 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
594 XML_ParserFree(ctx
.parser
);
599 XML_ParserFree(ctx
.parser
);
606 gen_spec_load_from_path(const struct gen_device_info
*devinfo
,
609 struct parser_context ctx
;
610 size_t len
, filename_len
= strlen(path
) + 20;
611 char *filename
= malloc(filename_len
);
615 len
= snprintf(filename
, filename_len
, "%s/gen%i.xml",
616 path
, devinfo_to_gen(devinfo
));
617 assert(len
< filename_len
);
619 input
= fopen(filename
, "r");
621 fprintf(stderr
, "failed to open xml description\n");
626 memset(&ctx
, 0, sizeof ctx
);
627 ctx
.parser
= XML_ParserCreate(NULL
);
628 XML_SetUserData(ctx
.parser
, &ctx
);
629 if (ctx
.parser
== NULL
) {
630 fprintf(stderr
, "failed to create parser\n");
636 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
637 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
638 ctx
.loc
.filename
= filename
;
639 ctx
.spec
= rzalloc(NULL
, struct gen_spec
);
642 buf
= XML_GetBuffer(ctx
.parser
, XML_BUFFER_SIZE
);
643 len
= fread(buf
, 1, XML_BUFFER_SIZE
, input
);
645 fprintf(stderr
, "fread: %m\n");
650 if (XML_ParseBuffer(ctx
.parser
, len
, len
== 0) == 0) {
652 "Error parsing XML at line %ld col %ld: %s\n",
653 XML_GetCurrentLineNumber(ctx
.parser
),
654 XML_GetCurrentColumnNumber(ctx
.parser
),
655 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
663 XML_ParserFree(ctx
.parser
);
671 void gen_spec_destroy(struct gen_spec
*spec
)
677 gen_spec_find_instruction(struct gen_spec
*spec
, const uint32_t *p
)
679 struct hash_entry
*entry
;
681 hash_table_foreach(spec
->commands
, entry
) {
682 struct gen_group
*command
= entry
->data
;
683 uint32_t opcode
= *p
& command
->opcode_mask
;
684 if (opcode
== command
->opcode
)
692 gen_group_get_length(struct gen_group
*group
, const uint32_t *p
)
695 uint32_t type
= field(h
, 29, 31);
699 uint32_t opcode
= field(h
, 23, 28);
703 return field(h
, 0, 7) + 2;
708 return field(h
, 0, 7) + 2;
711 case 3: /* Render */ {
712 uint32_t subtype
= field(h
, 27, 28);
713 uint32_t opcode
= field(h
, 24, 26);
714 uint16_t whole_opcode
= field(h
, 16, 31);
717 if (whole_opcode
== 0x6104 /* PIPELINE_SELECT_965 */)
720 return field(h
, 0, 7) + 2;
730 return field(h
, 0, 7) + 2;
732 return field(h
, 0, 15) + 2;
737 if (whole_opcode
== 0x780b)
740 return field(h
, 0, 7) + 2;
751 gen_get_enum_name(struct gen_enum
*e
, uint64_t value
)
753 for (int i
= 0; i
< e
->nvalues
; i
++) {
754 if (e
->values
[i
]->value
== value
) {
755 return e
->values
[i
]->name
;
762 iter_more_fields(const struct gen_field_iterator
*iter
)
764 return iter
->field
!= NULL
&& iter
->field
->next
!= NULL
;
768 iter_group_offset_bits(const struct gen_field_iterator
*iter
,
771 return iter
->group
->group_offset
+ (group_iter
* iter
->group
->group_size
);
775 iter_more_groups(const struct gen_field_iterator
*iter
)
777 if (iter
->group
->variable
) {
778 return iter_group_offset_bits(iter
, iter
->group_iter
+ 1) <
779 (gen_group_get_length(iter
->group
, iter
->p
) * 32);
781 return (iter
->group_iter
+ 1) < iter
->group
->group_count
||
782 iter
->group
->next
!= NULL
;
787 iter_advance_group(struct gen_field_iterator
*iter
)
789 if (iter
->group
->variable
)
792 if ((iter
->group_iter
+ 1) < iter
->group
->group_count
) {
795 iter
->group
= iter
->group
->next
;
796 iter
->group_iter
= 0;
800 iter
->field
= iter
->group
->fields
;
804 iter_advance_field(struct gen_field_iterator
*iter
)
806 while (!iter_more_fields(iter
)) {
807 if (!iter_more_groups(iter
))
810 iter_advance_group(iter
);
813 iter
->field
= iter
->field
->next
;
814 if (iter
->field
->name
)
815 strncpy(iter
->name
, iter
->field
->name
, sizeof(iter
->name
));
817 memset(iter
->name
, 0, sizeof(iter
->name
));
819 int group_member_offset
= iter_group_offset_bits(iter
, iter
->group_iter
);
821 iter
->start
= group_member_offset
+ iter
->field
->start
;
822 iter
->end
= group_member_offset
+ iter
->field
->end
;
823 iter
->dword
= iter
->start
/ 32;
824 iter
->struct_desc
= NULL
;
830 gen_field_decode(struct gen_field_iterator
*iter
)
837 if (iter
->field
->name
)
838 strncpy(iter
->name
, iter
->field
->name
, sizeof(iter
->name
));
840 memset(iter
->name
, 0, sizeof(iter
->name
));
842 memset(&v
, 0, sizeof(v
));
844 if ((iter
->field
->end
- iter
->field
->start
) > 32) {
845 if (&iter
->p
[iter
->dword
+ 1] < iter
->p_end
)
846 v
.qw
= ((uint64_t) iter
->p
[iter
->dword
+1] << 32);
847 v
.qw
|= iter
->p
[iter
->dword
];
849 v
.qw
= iter
->p
[iter
->dword
];
851 const char *enum_name
= NULL
;
853 switch (iter
->field
->type
.kind
) {
854 case GEN_TYPE_UNKNOWN
:
856 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
857 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRId64
, value
);
858 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, value
);
861 case GEN_TYPE_UINT
: {
862 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
863 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRIu64
, value
);
864 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, value
);
867 case GEN_TYPE_BOOL
: {
868 const char *true_string
=
869 iter
->print_colors
? "\e[0;35mtrue\e[0m" : "true";
870 snprintf(iter
->value
, sizeof(iter
->value
), "%s",
871 field(v
.qw
, iter
->start
, iter
->end
) ?
872 true_string
: "false");
876 snprintf(iter
->value
, sizeof(iter
->value
), "%f", v
.f
);
878 case GEN_TYPE_ADDRESS
:
879 case GEN_TYPE_OFFSET
:
880 snprintf(iter
->value
, sizeof(iter
->value
), "0x%08"PRIx64
,
881 field_address(v
.qw
, iter
->start
, iter
->end
));
883 case GEN_TYPE_STRUCT
:
884 snprintf(iter
->value
, sizeof(iter
->value
), "<struct %s>",
885 iter
->field
->type
.gen_struct
->name
);
887 gen_spec_find_struct(iter
->group
->spec
,
888 iter
->field
->type
.gen_struct
->name
);
890 case GEN_TYPE_UFIXED
:
891 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
892 (float) field(v
.qw
, iter
->start
, iter
->end
) /
893 (1 << iter
->field
->type
.f
));
895 case GEN_TYPE_SFIXED
:
896 /* FIXME: Sign extend extracted field. */
897 snprintf(iter
->value
, sizeof(iter
->value
), "%s", "foo");
901 case GEN_TYPE_ENUM
: {
902 uint64_t value
= field(v
.qw
, iter
->start
, iter
->end
);
903 snprintf(iter
->value
, sizeof(iter
->value
),
905 enum_name
= gen_get_enum_name(iter
->field
->type
.gen_enum
, value
);
910 if (strlen(iter
->group
->name
) == 0) {
911 int length
= strlen(iter
->name
);
912 snprintf(iter
->name
+ length
, sizeof(iter
->name
) - length
,
913 "[%i]", iter
->group_iter
);
917 int length
= strlen(iter
->value
);
918 snprintf(iter
->value
+ length
, sizeof(iter
->value
) - length
,
924 gen_field_iterator_init(struct gen_field_iterator
*iter
,
925 struct gen_group
*group
,
929 memset(iter
, 0, sizeof(*iter
));
933 iter
->field
= group
->fields
;
935 iter
->field
= group
->next
->fields
;
937 iter
->p_end
= &p
[gen_group_get_length(iter
->group
, iter
->p
)];
938 iter
->print_colors
= print_colors
;
940 gen_field_decode(iter
);
944 gen_field_iterator_next(struct gen_field_iterator
*iter
)
946 if (!iter_advance_field(iter
))
949 gen_field_decode(iter
);
955 print_dword_header(FILE *outfile
,
956 struct gen_field_iterator
*iter
,
957 uint64_t offset
, uint32_t dword
)
959 fprintf(outfile
, "0x%08"PRIx64
": 0x%08x : Dword %d\n",
960 offset
+ 4 * dword
, iter
->p
[dword
], dword
);
964 gen_field_is_header(struct gen_field
*field
)
968 if (field
->start
>= 32)
971 bits
= (1U << (field
->end
- field
->start
+ 1)) - 1;
972 bits
<<= field
->start
;
974 return (field
->parent
->opcode_mask
& bits
) != 0;
978 gen_print_group(FILE *outfile
, struct gen_group
*group
,
979 uint64_t offset
, const uint32_t *p
, bool color
)
981 struct gen_field_iterator iter
;
984 gen_field_iterator_init(&iter
, group
, p
, color
);
986 if (last_dword
!= iter
.dword
) {
987 for (int i
= last_dword
+ 1; i
<= iter
.dword
; i
++)
988 print_dword_header(outfile
, &iter
, offset
, i
);
989 last_dword
= iter
.dword
;
991 if (!gen_field_is_header(iter
.field
)) {
992 fprintf(outfile
, " %s: %s\n", iter
.name
, iter
.value
);
993 if (iter
.struct_desc
) {
994 uint64_t struct_offset
= offset
+ 4 * iter
.dword
;
995 gen_print_group(outfile
, iter
.struct_desc
, struct_offset
,
996 &p
[iter
.dword
], color
);
999 } while (gen_field_iterator_next(&iter
));