summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToni Lönnberg <[email protected]>2018-10-29 13:56:44 +0200
committerLionel Landwerlin <[email protected]>2018-10-30 12:43:00 +0000
commitd5a938c58d058270990d5e077ed5b72384c001de (patch)
tree3eed44fba776089906f8f7891030bccab6748109
parenta09cbaffbfb1dcf0b6ae41bbba21ae9bfdfb8a3b (diff)
intel/decoder: Use 'DWord Length' and 'bias' fields for packet length.
Use the 'DWord Length' and 'bias' fields from the instruction definition to parse the packet length from the command stream when possible. The hardcoded mechanism is used whenever an instruction doesn't have this field. Reviewed-by: Lionel Landwerlin <[email protected]>
-rw-r--r--src/intel/common/gen_decoder.c30
-rw-r--r--src/intel/common/gen_decoder.h2
2 files changed, 25 insertions, 7 deletions
diff --git a/src/intel/common/gen_decoder.c b/src/intel/common/gen_decoder.c
index f24d3ccf15d..8148b2f1489 100644
--- a/src/intel/common/gen_decoder.c
+++ b/src/intel/common/gen_decoder.c
@@ -163,11 +163,16 @@ create_group(struct parser_context *ctx,
group->spec = ctx->spec;
group->variable = false;
group->fixed_length = fixed_length;
+ group->dword_length_field = NULL;
+ group->dw_length = 0;
+ group->bias = 1;
for (int i = 0; atts[i]; i += 2) {
char *p;
if (strcmp(atts[i], "length") == 0) {
group->dw_length = strtoul(atts[i + 1], &p, 0);
+ } else if (strcmp(atts[i], "bias") == 0) {
+ group->bias = strtoul(atts[i + 1], &p, 0);
}
}
@@ -288,15 +293,18 @@ create_field(struct parser_context *ctx, const char **atts)
for (int i = 0; atts[i]; i += 2) {
char *p;
- if (strcmp(atts[i], "name") == 0)
+ if (strcmp(atts[i], "name") == 0) {
field->name = ralloc_strdup(field, atts[i + 1]);
- else if (strcmp(atts[i], "start") == 0)
+ if (strcmp(field->name, "DWord Length") == 0) {
+ field->parent->dword_length_field = field;
+ }
+ } else if (strcmp(atts[i], "start") == 0) {
field->start = strtoul(atts[i + 1], &p, 0);
- else if (strcmp(atts[i], "end") == 0) {
+ } else if (strcmp(atts[i], "end") == 0) {
field->end = strtoul(atts[i + 1], &p, 0);
- } else if (strcmp(atts[i], "type") == 0)
+ } else if (strcmp(atts[i], "type") == 0) {
field->type = string_to_type(ctx, atts[i + 1]);
- else if (strcmp(atts[i], "default") == 0 &&
+ } 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);
@@ -741,8 +749,16 @@ gen_group_find_field(struct gen_group *group, const char *name)
int
gen_group_get_length(struct gen_group *group, const uint32_t *p)
{
- if (group && group->fixed_length)
- return group->dw_length;
+ if (group) {
+ if (group->fixed_length)
+ return group->dw_length;
+ else {
+ struct gen_field *field = group->dword_length_field;
+ if (field) {
+ return field_value(p[0], field->start, field->end) + group->bias;
+ }
+ }
+ }
uint32_t h = p[0];
uint32_t type = field_value(h, 29, 31);
diff --git a/src/intel/common/gen_decoder.h b/src/intel/common/gen_decoder.h
index a80c50b6647..4beed22d729 100644
--- a/src/intel/common/gen_decoder.h
+++ b/src/intel/common/gen_decoder.h
@@ -99,8 +99,10 @@ struct gen_group {
char *name;
struct gen_field *fields; /* linked list of fields */
+ struct gen_field *dword_length_field; /* <instruction> specific */
uint32_t dw_length;
+ uint32_t bias; /* <instruction> specific */
uint32_t group_offset, group_count;
uint32_t group_size;
bool variable; /* <group> specific */