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"
39 #include "genxml/genX_xml.h"
41 #define XML_BUFFER_SIZE 4096
42 #define MAX_VALUE_ITEMS 128
49 struct parser_context
{
54 struct gen_group
*group
;
55 struct gen_enum
*enoom
;
57 int n_values
, n_allocated_values
;
58 struct gen_value
**values
;
60 struct gen_field
*last_field
;
62 struct gen_spec
*spec
;
66 gen_group_get_name(struct gen_group
*group
)
72 gen_group_get_opcode(struct gen_group
*group
)
78 gen_spec_find_struct(struct gen_spec
*spec
, const char *name
)
80 struct hash_entry
*entry
= _mesa_hash_table_search(spec
->structs
,
82 return entry
? entry
->data
: NULL
;
86 gen_spec_find_register(struct gen_spec
*spec
, uint32_t offset
)
88 struct hash_entry
*entry
=
89 _mesa_hash_table_search(spec
->registers_by_offset
,
90 (void *) (uintptr_t) offset
);
91 return entry
? entry
->data
: NULL
;
95 gen_spec_find_register_by_name(struct gen_spec
*spec
, const char *name
)
97 struct hash_entry
*entry
=
98 _mesa_hash_table_search(spec
->registers_by_name
, name
);
99 return entry
? entry
->data
: NULL
;
103 gen_spec_find_enum(struct gen_spec
*spec
, const char *name
)
105 struct hash_entry
*entry
= _mesa_hash_table_search(spec
->enums
,
107 return entry
? entry
->data
: NULL
;
111 gen_spec_get_gen(struct gen_spec
*spec
)
116 static void __attribute__((noreturn
))
117 fail(struct location
*loc
, const char *msg
, ...)
122 fprintf(stderr
, "%s:%d: error: ",
123 loc
->filename
, loc
->line_number
);
124 vfprintf(stderr
, msg
, ap
);
125 fprintf(stderr
, "\n");
131 get_array_offset_count(const char **atts
, uint32_t *offset
, uint32_t *count
,
132 uint32_t *size
, bool *variable
)
134 for (int i
= 0; atts
[i
]; i
+= 2) {
137 if (strcmp(atts
[i
], "count") == 0) {
138 *count
= strtoul(atts
[i
+ 1], &p
, 0);
141 } else if (strcmp(atts
[i
], "start") == 0) {
142 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
143 } else if (strcmp(atts
[i
], "size") == 0) {
144 *size
= strtoul(atts
[i
+ 1], &p
, 0);
150 static struct gen_group
*
151 create_group(struct parser_context
*ctx
,
154 struct gen_group
*parent
,
157 struct gen_group
*group
;
159 group
= rzalloc(ctx
->spec
, struct gen_group
);
161 group
->name
= ralloc_strdup(group
, name
);
163 group
->spec
= ctx
->spec
;
164 group
->variable
= false;
165 group
->fixed_length
= fixed_length
;
166 group
->dword_length_field
= NULL
;
167 group
->dw_length
= 0;
168 group
->engine_mask
= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER
) |
169 I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO
) |
170 I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY
);
173 for (int i
= 0; atts
[i
]; i
+= 2) {
175 if (strcmp(atts
[i
], "length") == 0) {
176 group
->dw_length
= strtoul(atts
[i
+ 1], &p
, 0);
177 } else if (strcmp(atts
[i
], "bias") == 0) {
178 group
->bias
= strtoul(atts
[i
+ 1], &p
, 0);
179 } else if (strcmp(atts
[i
], "engine") == 0) {
180 void *mem_ctx
= ralloc_context(NULL
);
181 char *tmp
= ralloc_strdup(mem_ctx
, atts
[i
+ 1]);
183 char *tok
= strtok_r(tmp
, "|", &save_ptr
);
185 group
->engine_mask
= 0;
186 while (tok
!= NULL
) {
187 if (strcmp(tok
, "render") == 0) {
188 group
->engine_mask
|= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_RENDER
);
189 } else if (strcmp(tok
, "video") == 0) {
190 group
->engine_mask
|= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_VIDEO
);
191 } else if (strcmp(tok
, "blitter") == 0) {
192 group
->engine_mask
|= I915_ENGINE_CLASS_TO_MASK(I915_ENGINE_CLASS_COPY
);
194 fprintf(stderr
, "unknown engine class defined for instruction \"%s\": %s\n", name
, atts
[i
+ 1]);
197 tok
= strtok_r(NULL
, "|", &save_ptr
);
200 ralloc_free(mem_ctx
);
205 group
->parent
= parent
;
206 get_array_offset_count(atts
,
207 &group
->array_offset
,
209 &group
->array_item_size
,
216 static struct gen_enum
*
217 create_enum(struct parser_context
*ctx
, const char *name
, const char **atts
)
221 e
= rzalloc(ctx
->spec
, struct gen_enum
);
223 e
->name
= ralloc_strdup(e
, name
);
229 get_register_offset(const char **atts
, uint32_t *offset
)
231 for (int i
= 0; atts
[i
]; i
+= 2) {
234 if (strcmp(atts
[i
], "num") == 0)
235 *offset
= strtoul(atts
[i
+ 1], &p
, 0);
241 get_start_end_pos(int *start
, int *end
)
243 /* start value has to be mod with 32 as we need the relative
244 * start position in the first DWord. For the end position, add
245 * the length of the field to the start position to get the
246 * relative postion in the 64 bit address.
248 if (*end
- *start
> 32) {
249 int len
= *end
- *start
;
250 *start
= *start
% 32;
253 *start
= *start
% 32;
260 static inline uint64_t
261 mask(int start
, int end
)
265 v
= ~0ULL >> (63 - end
+ start
);
270 static inline uint64_t
271 field_value(uint64_t value
, int start
, int end
)
273 get_start_end_pos(&start
, &end
);
274 return (value
& mask(start
, end
)) >> (start
);
277 static struct gen_type
278 string_to_type(struct parser_context
*ctx
, const char *s
)
284 if (strcmp(s
, "int") == 0)
285 return (struct gen_type
) { .kind
= GEN_TYPE_INT
};
286 else if (strcmp(s
, "uint") == 0)
287 return (struct gen_type
) { .kind
= GEN_TYPE_UINT
};
288 else if (strcmp(s
, "bool") == 0)
289 return (struct gen_type
) { .kind
= GEN_TYPE_BOOL
};
290 else if (strcmp(s
, "float") == 0)
291 return (struct gen_type
) { .kind
= GEN_TYPE_FLOAT
};
292 else if (strcmp(s
, "address") == 0)
293 return (struct gen_type
) { .kind
= GEN_TYPE_ADDRESS
};
294 else if (strcmp(s
, "offset") == 0)
295 return (struct gen_type
) { .kind
= GEN_TYPE_OFFSET
};
296 else if (sscanf(s
, "u%d.%d", &i
, &f
) == 2)
297 return (struct gen_type
) { .kind
= GEN_TYPE_UFIXED
, .i
= i
, .f
= f
};
298 else if (sscanf(s
, "s%d.%d", &i
, &f
) == 2)
299 return (struct gen_type
) { .kind
= GEN_TYPE_SFIXED
, .i
= i
, .f
= f
};
300 else if (g
= gen_spec_find_struct(ctx
->spec
, s
), g
!= NULL
)
301 return (struct gen_type
) { .kind
= GEN_TYPE_STRUCT
, .gen_struct
= g
};
302 else if (e
= gen_spec_find_enum(ctx
->spec
, s
), e
!= NULL
)
303 return (struct gen_type
) { .kind
= GEN_TYPE_ENUM
, .gen_enum
= e
};
304 else if (strcmp(s
, "mbo") == 0)
305 return (struct gen_type
) { .kind
= GEN_TYPE_MBO
};
307 fail(&ctx
->loc
, "invalid type: %s", s
);
310 static struct gen_field
*
311 create_field(struct parser_context
*ctx
, const char **atts
)
313 struct gen_field
*field
;
315 field
= rzalloc(ctx
->group
, struct gen_field
);
316 field
->parent
= ctx
->group
;
318 for (int i
= 0; atts
[i
]; i
+= 2) {
321 if (strcmp(atts
[i
], "name") == 0) {
322 field
->name
= ralloc_strdup(field
, atts
[i
+ 1]);
323 if (strcmp(field
->name
, "DWord Length") == 0) {
324 field
->parent
->dword_length_field
= field
;
326 } else if (strcmp(atts
[i
], "start") == 0) {
327 field
->start
= strtoul(atts
[i
+ 1], &p
, 0);
328 } else if (strcmp(atts
[i
], "end") == 0) {
329 field
->end
= strtoul(atts
[i
+ 1], &p
, 0);
330 } else if (strcmp(atts
[i
], "type") == 0) {
331 field
->type
= string_to_type(ctx
, atts
[i
+ 1]);
332 } else if (strcmp(atts
[i
], "default") == 0 &&
333 field
->start
>= 16 && field
->end
<= 31) {
334 field
->has_default
= true;
335 field
->default_value
= strtoul(atts
[i
+ 1], &p
, 0);
342 static struct gen_field
*
343 create_array_field(struct parser_context
*ctx
, struct gen_group
*array
)
345 struct gen_field
*field
;
347 field
= rzalloc(ctx
->group
, struct gen_field
);
348 field
->parent
= ctx
->group
;
350 field
->array
= array
;
351 field
->start
= field
->array
->array_offset
;
356 static struct gen_value
*
357 create_value(struct parser_context
*ctx
, const char **atts
)
359 struct gen_value
*value
= rzalloc(ctx
->values
, struct gen_value
);
361 for (int i
= 0; atts
[i
]; i
+= 2) {
362 if (strcmp(atts
[i
], "name") == 0)
363 value
->name
= ralloc_strdup(value
, atts
[i
+ 1]);
364 else if (strcmp(atts
[i
], "value") == 0)
365 value
->value
= strtoul(atts
[i
+ 1], NULL
, 0);
371 static struct gen_field
*
372 create_and_append_field(struct parser_context
*ctx
,
374 struct gen_group
*array
)
376 struct gen_field
*field
= array
?
377 create_array_field(ctx
, array
) : create_field(ctx
, atts
);
378 struct gen_field
*prev
= NULL
, *list
= ctx
->group
->fields
;
380 while (list
&& field
->start
> list
->start
) {
387 ctx
->group
->fields
= field
;
395 start_element(void *data
, const char *element_name
, const char **atts
)
397 struct parser_context
*ctx
= data
;
398 const char *name
= NULL
;
399 const char *gen
= NULL
;
401 ctx
->loc
.line_number
= XML_GetCurrentLineNumber(ctx
->parser
);
403 for (int i
= 0; atts
[i
]; i
+= 2) {
404 if (strcmp(atts
[i
], "name") == 0)
406 else if (strcmp(atts
[i
], "gen") == 0)
410 if (strcmp(element_name
, "genxml") == 0) {
412 fail(&ctx
->loc
, "no platform name given");
414 fail(&ctx
->loc
, "no gen given");
417 int n
= sscanf(gen
, "%d.%d", &major
, &minor
);
419 fail(&ctx
->loc
, "invalid gen given: %s", gen
);
423 ctx
->spec
->gen
= gen_make_gen(major
, minor
);
424 } else if (strcmp(element_name
, "instruction") == 0) {
425 ctx
->group
= create_group(ctx
, name
, atts
, NULL
, false);
426 } else if (strcmp(element_name
, "struct") == 0) {
427 ctx
->group
= create_group(ctx
, name
, atts
, NULL
, true);
428 } else if (strcmp(element_name
, "register") == 0) {
429 ctx
->group
= create_group(ctx
, name
, atts
, NULL
, true);
430 get_register_offset(atts
, &ctx
->group
->register_offset
);
431 } else if (strcmp(element_name
, "group") == 0) {
432 struct gen_group
*group
= create_group(ctx
, "", atts
, ctx
->group
, false);
433 ctx
->last_field
= create_and_append_field(ctx
, NULL
, group
);
435 } else if (strcmp(element_name
, "field") == 0) {
436 ctx
->last_field
= create_and_append_field(ctx
, atts
, NULL
);
437 } else if (strcmp(element_name
, "enum") == 0) {
438 ctx
->enoom
= create_enum(ctx
, name
, atts
);
439 } else if (strcmp(element_name
, "value") == 0) {
440 if (ctx
->n_values
>= ctx
->n_allocated_values
) {
441 ctx
->n_allocated_values
= MAX2(2, ctx
->n_allocated_values
* 2);
442 ctx
->values
= reralloc_array_size(ctx
->spec
, ctx
->values
,
443 sizeof(struct gen_value
*),
444 ctx
->n_allocated_values
);
446 assert(ctx
->n_values
< ctx
->n_allocated_values
);
447 ctx
->values
[ctx
->n_values
++] = create_value(ctx
, atts
);
453 end_element(void *data
, const char *name
)
455 struct parser_context
*ctx
= data
;
456 struct gen_spec
*spec
= ctx
->spec
;
458 if (strcmp(name
, "instruction") == 0 ||
459 strcmp(name
, "struct") == 0 ||
460 strcmp(name
, "register") == 0) {
461 struct gen_group
*group
= ctx
->group
;
462 struct gen_field
*list
= group
->fields
;
464 ctx
->group
= ctx
->group
->parent
;
466 while (list
&& list
->end
<= 31) {
467 if (list
->start
>= 16 && list
->has_default
) {
468 group
->opcode_mask
|=
469 mask(list
->start
% 32, list
->end
% 32);
470 group
->opcode
|= list
->default_value
<< list
->start
;
475 if (strcmp(name
, "instruction") == 0)
476 _mesa_hash_table_insert(spec
->commands
, group
->name
, group
);
477 else if (strcmp(name
, "struct") == 0)
478 _mesa_hash_table_insert(spec
->structs
, group
->name
, group
);
479 else if (strcmp(name
, "register") == 0) {
480 _mesa_hash_table_insert(spec
->registers_by_name
, group
->name
, group
);
481 _mesa_hash_table_insert(spec
->registers_by_offset
,
482 (void *) (uintptr_t) group
->register_offset
,
485 } else if (strcmp(name
, "group") == 0) {
486 ctx
->group
= ctx
->group
->parent
;
487 } else if (strcmp(name
, "field") == 0) {
488 struct gen_field
*field
= ctx
->last_field
;
489 ctx
->last_field
= NULL
;
490 field
->inline_enum
.values
= ctx
->values
;
491 field
->inline_enum
.nvalues
= ctx
->n_values
;
492 ctx
->values
= ralloc_array(ctx
->spec
, struct gen_value
*, ctx
->n_allocated_values
= 2);
494 } else if (strcmp(name
, "enum") == 0) {
495 struct gen_enum
*e
= ctx
->enoom
;
496 e
->values
= ctx
->values
;
497 e
->nvalues
= ctx
->n_values
;
498 ctx
->values
= ralloc_array(ctx
->spec
, struct gen_value
*, ctx
->n_allocated_values
= 2);
501 _mesa_hash_table_insert(spec
->enums
, e
->name
, e
);
506 character_data(void *data
, const XML_Char
*s
, int len
)
511 devinfo_to_gen(const struct gen_device_info
*devinfo
, bool x10
)
513 if (devinfo
->is_baytrail
|| devinfo
->is_haswell
) {
514 return devinfo
->gen
* 10 + 5;
517 return x10
? devinfo
->gen
* 10 : devinfo
->gen
;
520 static uint32_t zlib_inflate(const void *compressed_data
,
521 uint32_t compressed_len
,
524 struct z_stream_s zstream
;
527 memset(&zstream
, 0, sizeof(zstream
));
529 zstream
.next_in
= (unsigned char *)compressed_data
;
530 zstream
.avail_in
= compressed_len
;
532 if (inflateInit(&zstream
) != Z_OK
)
536 zstream
.next_out
= out
;
537 zstream
.avail_out
= 4096;
540 switch (inflate(&zstream
, Z_SYNC_FLUSH
)) {
546 inflateEnd(&zstream
);
550 if (zstream
.avail_out
)
553 out
= realloc(out
, 2*zstream
.total_out
);
555 inflateEnd(&zstream
);
559 zstream
.next_out
= (unsigned char *)out
+ zstream
.total_out
;
560 zstream
.avail_out
= zstream
.total_out
;
563 inflateEnd(&zstream
);
565 return zstream
.total_out
;
568 static uint32_t _hash_uint32(const void *key
)
570 return (uint32_t) (uintptr_t) key
;
573 static struct gen_spec
*
576 struct gen_spec
*spec
;
577 spec
= rzalloc(NULL
, struct gen_spec
);
582 _mesa_hash_table_create(spec
, _mesa_hash_string
, _mesa_key_string_equal
);
584 _mesa_hash_table_create(spec
, _mesa_hash_string
, _mesa_key_string_equal
);
585 spec
->registers_by_name
=
586 _mesa_hash_table_create(spec
, _mesa_hash_string
, _mesa_key_string_equal
);
587 spec
->registers_by_offset
=
588 _mesa_hash_table_create(spec
, _hash_uint32
, _mesa_key_pointer_equal
);
590 _mesa_hash_table_create(spec
, _mesa_hash_string
, _mesa_key_string_equal
);
592 _mesa_hash_table_create(spec
, _mesa_hash_string
, _mesa_key_string_equal
);
598 gen_spec_load(const struct gen_device_info
*devinfo
)
600 struct parser_context ctx
;
602 uint8_t *text_data
= NULL
;
603 uint32_t text_offset
= 0, text_length
= 0;
604 ASSERTED
uint32_t total_length
;
605 uint32_t gen_10
= devinfo_to_gen(devinfo
, true);
607 for (int i
= 0; i
< ARRAY_SIZE(genxml_files_table
); i
++) {
608 if (genxml_files_table
[i
].gen_10
== gen_10
) {
609 text_offset
= genxml_files_table
[i
].offset
;
610 text_length
= genxml_files_table
[i
].length
;
615 if (text_length
== 0) {
616 fprintf(stderr
, "unable to find gen (%u) data\n", gen_10
);
620 memset(&ctx
, 0, sizeof ctx
);
621 ctx
.parser
= XML_ParserCreate(NULL
);
622 XML_SetUserData(ctx
.parser
, &ctx
);
623 if (ctx
.parser
== NULL
) {
624 fprintf(stderr
, "failed to create parser\n");
628 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
629 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
631 ctx
.spec
= gen_spec_init();
632 if (ctx
.spec
== NULL
) {
633 fprintf(stderr
, "Failed to create gen_spec\n");
637 total_length
= zlib_inflate(compress_genxmls
,
638 sizeof(compress_genxmls
),
639 (void **) &text_data
);
640 assert(text_offset
+ text_length
<= total_length
);
642 buf
= XML_GetBuffer(ctx
.parser
, text_length
);
643 memcpy(buf
, &text_data
[text_offset
], text_length
);
645 if (XML_ParseBuffer(ctx
.parser
, text_length
, true) == 0) {
647 "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
648 XML_GetCurrentLineNumber(ctx
.parser
),
649 XML_GetCurrentColumnNumber(ctx
.parser
),
650 XML_GetCurrentByteIndex(ctx
.parser
), text_length
,
651 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
652 XML_ParserFree(ctx
.parser
);
657 XML_ParserFree(ctx
.parser
);
664 gen_spec_load_filename(const char *filename
)
666 struct parser_context ctx
;
671 input
= fopen(filename
, "r");
673 fprintf(stderr
, "failed to open xml description\n");
677 memset(&ctx
, 0, sizeof ctx
);
678 ctx
.parser
= XML_ParserCreate(NULL
);
679 XML_SetUserData(ctx
.parser
, &ctx
);
680 if (ctx
.parser
== NULL
) {
681 fprintf(stderr
, "failed to create parser\n");
686 XML_SetElementHandler(ctx
.parser
, start_element
, end_element
);
687 XML_SetCharacterDataHandler(ctx
.parser
, character_data
);
688 ctx
.loc
.filename
= filename
;
690 ctx
.spec
= gen_spec_init();
691 if (ctx
.spec
== NULL
) {
692 fprintf(stderr
, "Failed to create gen_spec\n");
697 buf
= XML_GetBuffer(ctx
.parser
, XML_BUFFER_SIZE
);
698 len
= fread(buf
, 1, XML_BUFFER_SIZE
, input
);
700 fprintf(stderr
, "fread: %m\n");
701 gen_spec_destroy(ctx
.spec
);
704 } else if (len
== 0 && feof(input
))
707 if (XML_ParseBuffer(ctx
.parser
, len
, len
== 0) == 0) {
709 "Error parsing XML at line %ld col %ld: %s\n",
710 XML_GetCurrentLineNumber(ctx
.parser
),
711 XML_GetCurrentColumnNumber(ctx
.parser
),
712 XML_ErrorString(XML_GetErrorCode(ctx
.parser
)));
713 gen_spec_destroy(ctx
.spec
);
720 XML_ParserFree(ctx
.parser
);
724 /* free ctx.spec if genxml is empty */
726 _mesa_hash_table_num_entries(ctx
.spec
->commands
) == 0 &&
727 _mesa_hash_table_num_entries(ctx
.spec
->structs
) == 0) {
729 "Error parsing XML: empty spec.\n");
730 gen_spec_destroy(ctx
.spec
);
738 gen_spec_load_from_path(const struct gen_device_info
*devinfo
,
741 size_t filename_len
= strlen(path
) + 20;
742 char *filename
= malloc(filename_len
);
744 ASSERTED
size_t len
= snprintf(filename
, filename_len
, "%s/gen%i.xml",
745 path
, devinfo_to_gen(devinfo
, false));
746 assert(len
< filename_len
);
748 struct gen_spec
*spec
= gen_spec_load_filename(filename
);
754 void gen_spec_destroy(struct gen_spec
*spec
)
760 gen_spec_find_instruction(struct gen_spec
*spec
,
761 enum drm_i915_gem_engine_class engine
,
764 hash_table_foreach(spec
->commands
, entry
) {
765 struct gen_group
*command
= entry
->data
;
766 uint32_t opcode
= *p
& command
->opcode_mask
;
767 if ((command
->engine_mask
& I915_ENGINE_CLASS_TO_MASK(engine
)) &&
768 opcode
== command
->opcode
)
776 gen_group_find_field(struct gen_group
*group
, const char *name
)
779 snprintf(path
, sizeof(path
), "%s/%s", group
->name
, name
);
781 struct gen_spec
*spec
= group
->spec
;
782 struct hash_entry
*entry
= _mesa_hash_table_search(spec
->access_cache
,
787 struct gen_field
*field
= group
->fields
;
789 if (strcmp(field
->name
, name
) == 0) {
790 _mesa_hash_table_insert(spec
->access_cache
,
791 ralloc_strdup(spec
, path
),
802 gen_group_get_length(struct gen_group
*group
, const uint32_t *p
)
805 if (group
->fixed_length
)
806 return group
->dw_length
;
808 struct gen_field
*field
= group
->dword_length_field
;
810 return field_value(p
[0], field
->start
, field
->end
) + group
->bias
;
816 uint32_t type
= field_value(h
, 29, 31);
820 uint32_t opcode
= field_value(h
, 23, 28);
824 return field_value(h
, 0, 7) + 2;
829 return field_value(h
, 0, 7) + 2;
832 case 3: /* Render */ {
833 uint32_t subtype
= field_value(h
, 27, 28);
834 uint32_t opcode
= field_value(h
, 24, 26);
835 uint16_t whole_opcode
= field_value(h
, 16, 31);
838 if (whole_opcode
== 0x6104 /* PIPELINE_SELECT_965 */)
841 return field_value(h
, 0, 7) + 2;
851 return field_value(h
, 0, 7) + 2;
853 return field_value(h
, 0, 15) + 2;
858 if (whole_opcode
== 0x780b)
861 return field_value(h
, 0, 7) + 2;
872 gen_get_enum_name(struct gen_enum
*e
, uint64_t value
)
874 for (int i
= 0; i
< e
->nvalues
; i
++) {
875 if (e
->values
[i
]->value
== value
) {
876 return e
->values
[i
]->name
;
883 iter_more_fields(const struct gen_field_iterator
*iter
)
885 return iter
->field
!= NULL
&& iter
->field
->next
!= NULL
;
889 iter_array_offset_bits(const struct gen_field_iterator
*iter
)
891 if (iter
->level
== 0)
895 const struct gen_group
*group
= iter
->groups
[1];
896 for (int level
= 1; level
<= iter
->level
; level
++, group
= iter
->groups
[level
]) {
897 uint32_t array_idx
= iter
->array_iter
[level
];
898 offset
+= group
->array_offset
+ array_idx
* group
->array_item_size
;
904 /* Checks whether we have more items in the array to iterate, or more arrays to
907 /* descend into a non-array field */
909 iter_push_array(struct gen_field_iterator
*iter
)
911 assert(iter
->level
>= 0);
913 iter
->group
= iter
->field
->array
;
915 assert(iter
->level
< DECODE_MAX_ARRAY_DEPTH
);
916 iter
->groups
[iter
->level
] = iter
->group
;
917 iter
->array_iter
[iter
->level
] = 0;
919 assert(iter
->group
->fields
!= NULL
); /* an empty <group> makes no sense */
920 iter
->field
= iter
->group
->fields
;
921 iter
->fields
[iter
->level
] = iter
->field
;
925 iter_pop_array(struct gen_field_iterator
*iter
)
927 assert(iter
->level
> 0);
930 iter
->field
= iter
->fields
[iter
->level
];
931 iter
->group
= iter
->groups
[iter
->level
];
935 iter_start_field(struct gen_field_iterator
*iter
, struct gen_field
*field
)
938 iter
->fields
[iter
->level
] = field
;
940 while (iter
->field
->array
)
941 iter_push_array(iter
);
943 int array_member_offset
= iter_array_offset_bits(iter
);
945 iter
->start_bit
= array_member_offset
+ iter
->field
->start
;
946 iter
->end_bit
= array_member_offset
+ iter
->field
->end
;
947 iter
->struct_desc
= NULL
;
951 iter_advance_array(struct gen_field_iterator
*iter
)
953 assert(iter
->level
> 0);
954 int lvl
= iter
->level
;
956 if (iter
->group
->variable
)
957 iter
->array_iter
[lvl
]++;
959 if ((iter
->array_iter
[lvl
] + 1) < iter
->group
->array_count
) {
960 iter
->array_iter
[lvl
]++;
964 iter_start_field(iter
, iter
->group
->fields
);
968 iter_more_array_elems(const struct gen_field_iterator
*iter
)
970 int lvl
= iter
->level
;
973 if (iter
->group
->variable
) {
974 int length
= gen_group_get_length(iter
->group
, iter
->p
);
975 assert(length
>= 0 && "error the length is unknown!");
976 return iter_array_offset_bits(iter
) + iter
->group
->array_item_size
<
979 return (iter
->array_iter
[lvl
] + 1) < iter
->group
->array_count
;
984 iter_advance_field(struct gen_field_iterator
*iter
)
986 /* Keep looping while we either have more fields to look at, or we are
987 * inside a <group> and can go up a level.
989 while (iter_more_fields(iter
) || iter
->level
> 0) {
990 if (iter_more_fields(iter
)) {
991 iter_start_field(iter
, iter
->field
->next
);
995 assert(iter
->level
>= 0);
997 if (iter_more_array_elems(iter
)) {
998 iter_advance_array(iter
);
1002 /* At this point, we reached the end of the <group> and were on the last
1003 * iteration. So it's time to go back to the parent and then advance the
1006 iter_pop_array(iter
);
1013 iter_decode_field_raw(struct gen_field_iterator
*iter
, uint64_t *qw
)
1017 int field_start
= iter
->p_bit
+ iter
->start_bit
;
1018 int field_end
= iter
->p_bit
+ iter
->end_bit
;
1020 const uint32_t *p
= iter
->p
+ (iter
->start_bit
/ 32);
1021 if (iter
->p_end
&& p
>= iter
->p_end
)
1024 if ((field_end
- field_start
) > 32) {
1025 if (!iter
->p_end
|| (p
+ 1) < iter
->p_end
)
1026 *qw
= ((uint64_t) p
[1]) << 32;
1031 *qw
= field_value(*qw
, field_start
, field_end
);
1033 /* Address & offset types have to be aligned to dwords, their start bit is
1034 * a reminder of the alignment requirement.
1036 if (iter
->field
->type
.kind
== GEN_TYPE_ADDRESS
||
1037 iter
->field
->type
.kind
== GEN_TYPE_OFFSET
)
1038 *qw
<<= field_start
% 32;
1044 iter_decode_field(struct gen_field_iterator
*iter
)
1051 if (iter
->field
->name
)
1052 snprintf(iter
->name
, sizeof(iter
->name
), "%s", iter
->field
->name
);
1054 memset(iter
->name
, 0, sizeof(iter
->name
));
1056 memset(&v
, 0, sizeof(v
));
1058 if (!iter_decode_field_raw(iter
, &iter
->raw_value
))
1061 const char *enum_name
= NULL
;
1063 v
.qw
= iter
->raw_value
;
1064 switch (iter
->field
->type
.kind
) {
1065 case GEN_TYPE_UNKNOWN
:
1066 case GEN_TYPE_INT
: {
1067 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRId64
, v
.qw
);
1068 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, v
.qw
);
1071 case GEN_TYPE_UINT
: {
1072 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRIu64
, v
.qw
);
1073 enum_name
= gen_get_enum_name(&iter
->field
->inline_enum
, v
.qw
);
1076 case GEN_TYPE_BOOL
: {
1077 const char *true_string
=
1078 iter
->print_colors
? "\e[0;35mtrue\e[0m" : "true";
1079 snprintf(iter
->value
, sizeof(iter
->value
), "%s",
1080 v
.qw
? true_string
: "false");
1083 case GEN_TYPE_FLOAT
:
1084 snprintf(iter
->value
, sizeof(iter
->value
), "%f", v
.f
);
1086 case GEN_TYPE_ADDRESS
:
1087 case GEN_TYPE_OFFSET
:
1088 snprintf(iter
->value
, sizeof(iter
->value
), "0x%08"PRIx64
, v
.qw
);
1090 case GEN_TYPE_STRUCT
:
1091 snprintf(iter
->value
, sizeof(iter
->value
), "<struct %s>",
1092 iter
->field
->type
.gen_struct
->name
);
1094 gen_spec_find_struct(iter
->group
->spec
,
1095 iter
->field
->type
.gen_struct
->name
);
1097 case GEN_TYPE_UFIXED
:
1098 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
1099 (float) v
.qw
/ (1 << iter
->field
->type
.f
));
1101 case GEN_TYPE_SFIXED
: {
1102 /* Sign extend before converting */
1103 int bits
= iter
->field
->type
.i
+ iter
->field
->type
.f
+ 1;
1104 int64_t v_sign_extend
= ((int64_t)(v
.qw
<< (64 - bits
))) >> (64 - bits
);
1105 snprintf(iter
->value
, sizeof(iter
->value
), "%f",
1106 (float) v_sign_extend
/ (1 << iter
->field
->type
.f
));
1111 case GEN_TYPE_ENUM
: {
1112 snprintf(iter
->value
, sizeof(iter
->value
), "%"PRId64
, v
.qw
);
1113 enum_name
= gen_get_enum_name(iter
->field
->type
.gen_enum
, v
.qw
);
1118 if (strlen(iter
->group
->name
) == 0) {
1119 int length
= strlen(iter
->name
);
1120 assert(iter
->level
>= 0);
1123 char *buf
= iter
->name
+ length
;
1124 while (level
<= iter
->level
) {
1125 int printed
= snprintf(buf
, sizeof(iter
->name
) - length
,
1126 "[%i]", iter
->array_iter
[level
]);
1134 int length
= strlen(iter
->value
);
1135 snprintf(iter
->value
+ length
, sizeof(iter
->value
) - length
,
1136 " (%s)", enum_name
);
1137 } else if (strcmp(iter
->name
, "Surface Format") == 0 ||
1138 strcmp(iter
->name
, "Source Element Format") == 0) {
1139 if (isl_format_is_valid((enum isl_format
)v
.qw
)) {
1140 const char *fmt_name
= isl_format_get_name((enum isl_format
)v
.qw
);
1141 int length
= strlen(iter
->value
);
1142 snprintf(iter
->value
+ length
, sizeof(iter
->value
) - length
,
1151 gen_field_iterator_init(struct gen_field_iterator
*iter
,
1152 struct gen_group
*group
,
1153 const uint32_t *p
, int p_bit
,
1156 memset(iter
, 0, sizeof(*iter
));
1158 iter
->groups
[iter
->level
] = group
;
1159 iter
->group
= group
;
1161 iter
->p_bit
= p_bit
;
1163 int length
= gen_group_get_length(iter
->group
, iter
->p
);
1164 assert(length
>= 0 && "error the length is unknown!");
1165 iter
->p_end
= length
>= 0 ? &p
[length
] : NULL
;
1166 iter
->print_colors
= print_colors
;
1170 gen_field_iterator_next(struct gen_field_iterator
*iter
)
1172 /* Initial condition */
1174 if (iter
->group
->fields
)
1175 iter_start_field(iter
, iter
->group
->fields
);
1177 bool result
= iter_decode_field(iter
);
1178 if (!result
&& iter
->p_end
) {
1179 /* We're dealing with a non empty struct of length=0 (BLEND_STATE on
1182 assert(iter
->group
->dw_length
== 0);
1188 if (!iter_advance_field(iter
))
1191 if (!iter_decode_field(iter
))
1198 print_dword_header(FILE *outfile
,
1199 struct gen_field_iterator
*iter
,
1200 uint64_t offset
, uint32_t dword
)
1202 fprintf(outfile
, "0x%08"PRIx64
": 0x%08x : Dword %d\n",
1203 offset
+ 4 * dword
, iter
->p
[dword
], dword
);
1207 gen_field_is_header(struct gen_field
*field
)
1211 if (field
->start
>= 32)
1214 bits
= (1U << (field
->end
- field
->start
+ 1)) - 1;
1215 bits
<<= field
->start
;
1217 return (field
->parent
->opcode_mask
& bits
) != 0;
1221 gen_print_group(FILE *outfile
, struct gen_group
*group
, uint64_t offset
,
1222 const uint32_t *p
, int p_bit
, bool color
)
1224 struct gen_field_iterator iter
;
1225 int last_dword
= -1;
1227 gen_field_iterator_init(&iter
, group
, p
, p_bit
, color
);
1228 while (gen_field_iterator_next(&iter
)) {
1229 int iter_dword
= iter
.end_bit
/ 32;
1230 if (last_dword
!= iter_dword
) {
1231 for (int i
= last_dword
+ 1; i
<= iter_dword
; i
++)
1232 print_dword_header(outfile
, &iter
, offset
, i
);
1233 last_dword
= iter_dword
;
1235 if (!gen_field_is_header(iter
.field
)) {
1236 fprintf(outfile
, " %s: %s\n", iter
.name
, iter
.value
);
1237 if (iter
.struct_desc
) {
1238 int struct_dword
= iter
.start_bit
/ 32;
1239 uint64_t struct_offset
= offset
+ 4 * struct_dword
;
1240 gen_print_group(outfile
, iter
.struct_desc
, struct_offset
,
1241 &p
[struct_dword
], iter
.start_bit
% 32, color
);