diff --git a/src/intel/decoder/intel_decoder.c b/src/intel/decoder/intel_decoder.c
index 08c70bc89e7..f6436b6c363 100644
--- a/src/intel/decoder/intel_decoder.c
+++ b/src/intel/decoder/intel_decoder.c
@@ -147,6 +147,11 @@ static void
get_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count,
uint32_t *size, bool *variable)
{
+ bool is_old_format = false;
+ bool is_new_format = false;
+
+ *offset = 0;
+
for (int i = 0; atts[i]; i += 2) {
char *p;
@@ -155,12 +160,21 @@ get_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count,
if (*count == 0)
*variable = true;
} else if (strcmp(atts[i], "start") == 0) {
+ assert(!is_new_format);
+ is_old_format = true;
*offset = strtoul(atts[i + 1], &p, 0);
+ } else if (strcmp(atts[i], "dword") == 0) {
+ assert(!is_old_format);
+ is_new_format = true;
+ *offset += 32 * strtoul(atts[i + 1], &p, 0);
+ } else if (strcmp(atts[i], "offset_bits") == 0) {
+ assert(!is_old_format);
+ is_new_format = true;
+ *offset += strtoul(atts[i + 1], &p, 0);
} else if (strcmp(atts[i], "size") == 0) {
*size = strtoul(atts[i + 1], &p, 0);
}
}
- return;
}
static struct intel_group *
@@ -336,6 +350,16 @@ create_field(struct parser_context *ctx, const char **atts)
field = rzalloc(ctx->group, struct intel_field);
field->parent = ctx->group;
+ bool is_old_format = false;
+ bool is_new_format = false;
+
+ uint32_t dword = 0;
+ uint32_t bits_start = 0;
+ uint32_t bits_end = 0;
+
+ bool has_default = false;
+ uint32_t default_value = 0;
+
for (int i = 0; atts[i]; i += 2) {
char *p;
@@ -345,18 +369,41 @@ create_field(struct parser_context *ctx, const char **atts)
field->parent->dword_length_field = field;
}
} else if (strcmp(atts[i], "start") == 0) {
- field->start = strtoul(atts[i + 1], &p, 0);
+ assert(!is_new_format);
+ is_old_format = true;
+ bits_start = strtoul(atts[i + 1], &p, 0);
} else if (strcmp(atts[i], "end") == 0) {
- field->end = strtoul(atts[i + 1], &p, 0);
+ assert(!is_new_format);
+ is_old_format = true;
+ bits_end = strtoul(atts[i + 1], &p, 0);
+ } else if (strcmp(atts[i], "dword") == 0) {
+ assert(!is_old_format);
+ is_new_format = true;
+ dword = strtoul(atts[i + 1], &p, 10);
+ } else if (strcmp(atts[i], "bits") == 0) {
+ assert(!is_old_format);
+ is_new_format = true;
+ const char *bits_str = atts[i + 1];
+ const char *colon = strchr(bits_str, ':');
+ assert(colon);
+ bits_end = strtoul(bits_str, NULL, 10);
+ bits_start = strtoul(colon+1, NULL, 10);
} else if (strcmp(atts[i], "type") == 0) {
field->type = string_to_type(ctx, atts[i + 1]);
- } else if (strcmp(atts[i], "default") == 0 &&
- field->start >= 16 && field->end <= 31) {
- field->has_default = true;
- field->default_value = strtoul(atts[i + 1], &p, 0);
+ } else if (strcmp(atts[i], "default") == 0) {
+ has_default = true;
+ default_value = strtoul(atts[i + 1], &p, 0);
}
}
+ field->start = dword * 32 + bits_start;
+ field->end = dword * 32 + bits_end;
+
+ if (has_default && field->start >= 16 && field->end <= 31) {
+ field->has_default = true;
+ field->default_value = default_value;
+ }
+
return field;
}
diff --git a/src/intel/decoder/tests/gentest.xml b/src/intel/decoder/tests/gentest.xml
index 2b4af514a7a..60bbe0b3c4c 100644
--- a/src/intel/decoder/tests/gentest.xml
+++ b/src/intel/decoder/tests/gentest.xml
@@ -7,6 +7,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/intel/decoder/tests/genxml_test.c b/src/intel/decoder/tests/genxml_test.c
index 10b78f0cc63..3d17e92c421 100644
--- a/src/intel/decoder/tests/genxml_test.c
+++ b/src/intel/decoder/tests/genxml_test.c
@@ -127,6 +127,86 @@ test_two_levels(struct intel_spec *spec) {
}
}
+static void
+test_dword_fields(struct intel_spec *spec) {
+ struct GFX9_TEST_DWORD_FIELDS test = {
+ .value_dw0 = 0x1234,
+ .value_dw1 = 0xABCDEF00,
+ .value_dw2 = 0x5678,
+ .single_bit = true,
+ };
+
+ uint32_t dw[GFX9_TEST_DWORD_FIELDS_length];
+ GFX9_TEST_DWORD_FIELDS_pack(NULL, dw, &test);
+
+ struct intel_group *group;
+ group = intel_spec_find_struct(spec, "TEST_DWORD_FIELDS");
+
+ assert(group != NULL);
+
+ if (!quiet) {
+ printf("\nTEST_DWORD_FIELDS:\n");
+ intel_print_group(stdout, group, 0, dw, 0, false);
+ }
+
+ struct intel_field_iterator iter;
+ intel_field_iterator_init(&iter, group, dw, 0, false);
+
+ while (intel_field_iterator_next(&iter)) {
+ if (strcmp(iter.name, "value_dw0") == 0) {
+ uint16_t value = iter.raw_value;
+ assert(value == test.value_dw0);
+ } else if (strcmp(iter.name, "value_dw1") == 0) {
+ uint32_t value = iter.raw_value;
+ assert(value == test.value_dw1);
+ } else if (strcmp(iter.name, "value_dw2") == 0) {
+ uint16_t value = iter.raw_value;
+ assert(value == test.value_dw2);
+ } else if (strcmp(iter.name, "single_bit") == 0) {
+ bool value = iter.raw_value;
+ assert(value == test.single_bit);
+ }
+ }
+}
+
+static void
+test_offset_bits(struct intel_spec *spec) {
+ struct GFX9_TEST_OFFSET_BITS test = {
+ .header = 0x12345678,
+ };
+
+ for (int i = 0; i < 3; i++) {
+ test.data[i] = 0x1000 + i;
+ }
+
+ uint32_t dw[GFX9_TEST_OFFSET_BITS_length];
+ GFX9_TEST_OFFSET_BITS_pack(NULL, dw, &test);
+
+ struct intel_group *group;
+ group = intel_spec_find_struct(spec, "TEST_OFFSET_BITS");
+
+ assert(group != NULL);
+
+ if (!quiet) {
+ printf("\nTEST_OFFSET_BITS:\n");
+ intel_print_group(stdout, group, 0, dw, 0, false);
+ }
+
+ struct intel_field_iterator iter;
+ intel_field_iterator_init(&iter, group, dw, 0, false);
+
+ while (intel_field_iterator_next(&iter)) {
+ int idx;
+ if (strcmp(iter.name, "header") == 0) {
+ uint32_t value = iter.raw_value;
+ assert(value == test.header);
+ } else if (sscanf(iter.name, "data[%d]", &idx) == 1) {
+ uint16_t value = iter.raw_value;
+ assert(value == test.data[idx]);
+ }
+ }
+}
+
int main(int argc, char **argv)
{
struct intel_spec *spec = intel_spec_load_filename(GENXML_DIR, GENXML_FILE);
@@ -136,6 +216,8 @@ int main(int argc, char **argv)
test_struct(spec);
test_two_levels(spec);
+ test_dword_fields(spec);
+ test_offset_bits(spec);
intel_spec_destroy(spec);
diff --git a/src/intel/genxml/gen_bits_header.py b/src/intel/genxml/gen_bits_header.py
index 9399a09ad15..e1d05c5f9b5 100644
--- a/src/intel/genxml/gen_bits_header.py
+++ b/src/intel/genxml/gen_bits_header.py
@@ -213,9 +213,16 @@ class Field(object):
def add_gen(self, gen, xml_attrs):
assert isinstance(gen, Gen)
- start = int(xml_attrs['start'])
- end = int(xml_attrs['end'])
- self.start_by_gen[gen] = start
+
+ if 'start' in xml_attrs:
+ dword = 0
+ start = int(xml_attrs['start'])
+ end = int(xml_attrs['end'])
+ else:
+ dword = int(xml_attrs['dword'])
+ end, start = map(int, xml_attrs['bits'].split(':'))
+
+ self.start_by_gen[gen] = dword * 32 + start
self.bits_by_gen[gen] = 1 + end - start
def has_prop(self, prop):
diff --git a/src/intel/genxml/gen_pack_header.py b/src/intel/genxml/gen_pack_header.py
index 8790bdd98e3..edf807d08c1 100644
--- a/src/intel/genxml/gen_pack_header.py
+++ b/src/intel/genxml/gen_pack_header.py
@@ -72,8 +72,17 @@ class Field(object):
self.parser = parser
if "name" in attrs:
self.name = safe_name(attrs["name"])
- self.start = int(attrs["start"])
- self.end = int(attrs["end"])
+
+ if "start" in attrs:
+ self.start = int(attrs["start"])
+ self.end = int(attrs["end"])
+ else:
+ dword = int(attrs["dword"])
+ end_bit, start_bit = map(int, attrs["bits"].split(":"))
+
+ self.start = dword * 32 + start_bit
+ self.end = dword * 32 + end_bit
+
self.type = attrs["type"]
self.nonzero = bool_from_str(attrs.get("nonzero", "false"))
self.prefix = attrs["prefix"] if "prefix" in attrs else None
@@ -458,8 +467,15 @@ class Parser(object):
self.group = Group(self, None, 0, 1, size)
elif name == "group":
+ if "start" in attrs:
+ start = int(attrs["start"])
+ else:
+ dword = int(attrs["dword"])
+ offset_bits = int(attrs.get("offset_bits", 0))
+ start = dword * 32 + offset_bits
+
group = Group(self, self.group,
- int(attrs["start"]), int(attrs["count"]), int(attrs["size"]))
+ start, int(attrs["count"]), int(attrs["size"]))
self.group.fields.append(group)
self.group = group
elif name == "field":