1/*
2 * Copyright © 2016 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 */
23
24#include <stdio.h>
25#include <stdbool.h>
26#include <stdint.h>
27#include <stdarg.h>
28#include <string.h>
29#include <expat.h>
30#include <inttypes.h>
31#include <zlib.h>
32
33#include <util/macros.h>
34#include <util/ralloc.h>
35
36#include "gen_decoder.h"
37
38#include "isl/isl.h"
39#include "genxml/genX_xml.h"
40
41#define XML_BUFFER_SIZE 4096
42#define MAX_VALUE_ITEMS 128
43
44struct location {
45   const char *filename;
46   int line_number;
47};
48
49struct parser_context {
50   XML_Parser parser;
51   int foo;
52   struct location loc;
53
54   struct gen_group *group;
55   struct gen_enum *enoom;
56
57   int n_values, n_allocated_values;
58   struct gen_value **values;
59
60   struct gen_field *last_field;
61
62   struct gen_spec *spec;
63};
64
65const char *
66gen_group_get_name(struct gen_group *group)
67{
68   return group->name;
69}
70
71uint32_t
72gen_group_get_opcode(struct gen_group *group)
73{
74   return group->opcode;
75}
76
77struct gen_group *
78gen_spec_find_struct(struct gen_spec *spec, const char *name)
79{
80   struct hash_entry *entry = _mesa_hash_table_search(spec->structs,
81                                                      name);
82   return entry ? entry->data : NULL;
83}
84
85struct gen_group *
86gen_spec_find_register(struct gen_spec *spec, uint32_t offset)
87{
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;
92}
93
94struct gen_group *
95gen_spec_find_register_by_name(struct gen_spec *spec, const char *name)
96{
97   struct hash_entry *entry =
98      _mesa_hash_table_search(spec->registers_by_name, name);
99   return entry ? entry->data : NULL;
100}
101
102struct gen_enum *
103gen_spec_find_enum(struct gen_spec *spec, const char *name)
104{
105   struct hash_entry *entry = _mesa_hash_table_search(spec->enums,
106                                                      name);
107   return entry ? entry->data : NULL;
108}
109
110uint32_t
111gen_spec_get_gen(struct gen_spec *spec)
112{
113   return spec->gen;
114}
115
116static void __attribute__((noreturn))
117fail(struct location *loc, const char *msg, ...)
118{
119   va_list ap;
120
121   va_start(ap, msg);
122   fprintf(stderr, "%s:%d: error: ",
123           loc->filename, loc->line_number);
124   vfprintf(stderr, msg, ap);
125   fprintf(stderr, "\n");
126   va_end(ap);
127   exit(EXIT_FAILURE);
128}
129
130static void
131get_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count,
132                       uint32_t *size, bool *variable)
133{
134   for (int i = 0; atts[i]; i += 2) {
135      char *p;
136
137      if (strcmp(atts[i], "count") == 0) {
138         *count = strtoul(atts[i + 1], &p, 0);
139         if (*count == 0)
140            *variable = true;
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);
145      }
146   }
147   return;
148}
149
150static struct gen_group *
151create_group(struct parser_context *ctx,
152             const char *name,
153             const char **atts,
154             struct gen_group *parent,
155             bool fixed_length)
156{
157   struct gen_group *group;
158
159   group = rzalloc(ctx->spec, struct gen_group);
160   if (name)
161      group->name = ralloc_strdup(group, name);
162
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);
171   group->bias = 1;
172
173   for (int i = 0; atts[i]; i += 2) {
174      char *p;
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]);
182         char *save_ptr;
183         char *tok = strtok_r(tmp, "|", &save_ptr);
184
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);
193            } else {
194               fprintf(stderr, "unknown engine class defined for instruction \"%s\": %s\n", name, atts[i + 1]);
195            }
196
197            tok = strtok_r(NULL, "|", &save_ptr);
198         }
199
200         ralloc_free(mem_ctx);
201      }
202   }
203
204   if (parent) {
205      group->parent = parent;
206      get_group_offset_count(atts,
207                             &group->group_offset,
208                             &group->group_count,
209                             &group->group_size,
210                             &group->variable);
211   }
212
213   return group;
214}
215
216static struct gen_enum *
217create_enum(struct parser_context *ctx, const char *name, const char **atts)
218{
219   struct gen_enum *e;
220
221   e = rzalloc(ctx->spec, struct gen_enum);
222   if (name)
223      e->name = ralloc_strdup(e, name);
224
225   return e;
226}
227
228static void
229get_register_offset(const char **atts, uint32_t *offset)
230{
231   for (int i = 0; atts[i]; i += 2) {
232      char *p;
233
234      if (strcmp(atts[i], "num") == 0)
235         *offset = strtoul(atts[i + 1], &p, 0);
236   }
237   return;
238}
239
240static void
241get_start_end_pos(int *start, int *end)
242{
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.
247    */
248   if (*end - *start > 32) {
249      int len = *end - *start;
250      *start = *start % 32;
251      *end = *start + len;
252   } else {
253      *start = *start % 32;
254      *end = *end % 32;
255   }
256
257   return;
258}
259
260static inline uint64_t
261mask(int start, int end)
262{
263   uint64_t v;
264
265   v = ~0ULL >> (63 - end + start);
266
267   return v << start;
268}
269
270static inline uint64_t
271field_value(uint64_t value, int start, int end)
272{
273   get_start_end_pos(&start, &end);
274   return (value & mask(start, end)) >> (start);
275}
276
277static struct gen_type
278string_to_type(struct parser_context *ctx, const char *s)
279{
280   int i, f;
281   struct gen_group *g;
282   struct gen_enum *e;
283
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 };
306   else
307      fail(&ctx->loc, "invalid type: %s", s);
308}
309
310static struct gen_field *
311create_field(struct parser_context *ctx, const char **atts)
312{
313   struct gen_field *field;
314
315   field = rzalloc(ctx->group, struct gen_field);
316   field->parent = ctx->group;
317
318   for (int i = 0; atts[i]; i += 2) {
319      char *p;
320
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;
325         }
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);
336      }
337   }
338
339   return field;
340}
341
342static struct gen_value *
343create_value(struct parser_context *ctx, const char **atts)
344{
345   struct gen_value *value = rzalloc(ctx->values, struct gen_value);
346
347   for (int i = 0; atts[i]; i += 2) {
348      if (strcmp(atts[i], "name") == 0)
349         value->name = ralloc_strdup(value, atts[i + 1]);
350      else if (strcmp(atts[i], "value") == 0)
351         value->value = strtoul(atts[i + 1], NULL, 0);
352   }
353
354   return value;
355}
356
357static struct gen_field *
358create_and_append_field(struct parser_context *ctx,
359                        const char **atts)
360{
361   struct gen_field *field = create_field(ctx, atts);
362   struct gen_field *prev = NULL, *list = ctx->group->fields;
363
364   while (list && field->start > list->start) {
365      prev = list;
366      list = list->next;
367   }
368
369   field->next = list;
370   if (prev == NULL)
371      ctx->group->fields = field;
372   else
373      prev->next = field;
374
375   return field;
376}
377
378static void
379start_element(void *data, const char *element_name, const char **atts)
380{
381   struct parser_context *ctx = data;
382   const char *name = NULL;
383   const char *gen = NULL;
384
385   ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
386
387   for (int i = 0; atts[i]; i += 2) {
388      if (strcmp(atts[i], "name") == 0)
389         name = atts[i + 1];
390      else if (strcmp(atts[i], "gen") == 0)
391         gen = atts[i + 1];
392   }
393
394   if (strcmp(element_name, "genxml") == 0) {
395      if (name == NULL)
396         fail(&ctx->loc, "no platform name given");
397      if (gen == NULL)
398         fail(&ctx->loc, "no gen given");
399
400      int major, minor;
401      int n = sscanf(gen, "%d.%d", &major, &minor);
402      if (n == 0)
403         fail(&ctx->loc, "invalid gen given: %s", gen);
404      if (n == 1)
405         minor = 0;
406
407      ctx->spec->gen = gen_make_gen(major, minor);
408   } else if (strcmp(element_name, "instruction") == 0) {
409      ctx->group = create_group(ctx, name, atts, NULL, false);
410   } else if (strcmp(element_name, "struct") == 0) {
411      ctx->group = create_group(ctx, name, atts, NULL, true);
412   } else if (strcmp(element_name, "register") == 0) {
413      ctx->group = create_group(ctx, name, atts, NULL, true);
414      get_register_offset(atts, &ctx->group->register_offset);
415   } else if (strcmp(element_name, "group") == 0) {
416      struct gen_group *previous_group = ctx->group;
417      while (previous_group->next)
418         previous_group = previous_group->next;
419
420      struct gen_group *group = create_group(ctx, "", atts, ctx->group, false);
421      previous_group->next = group;
422      ctx->group = group;
423   } else if (strcmp(element_name, "field") == 0) {
424      ctx->last_field = create_and_append_field(ctx, atts);
425   } else if (strcmp(element_name, "enum") == 0) {
426      ctx->enoom = create_enum(ctx, name, atts);
427   } else if (strcmp(element_name, "value") == 0) {
428      if (ctx->n_values >= ctx->n_allocated_values) {
429         ctx->n_allocated_values = MAX2(2, ctx->n_allocated_values * 2);
430         ctx->values = reralloc_array_size(ctx->spec, ctx->values,
431                                           sizeof(struct gen_value *),
432                                           ctx->n_allocated_values);
433      }
434      assert(ctx->n_values < ctx->n_allocated_values);
435      ctx->values[ctx->n_values++] = create_value(ctx, atts);
436   }
437
438}
439
440static void
441end_element(void *data, const char *name)
442{
443   struct parser_context *ctx = data;
444   struct gen_spec *spec = ctx->spec;
445
446   if (strcmp(name, "instruction") == 0 ||
447       strcmp(name, "struct") == 0 ||
448       strcmp(name, "register") == 0) {
449      struct gen_group *group = ctx->group;
450      struct gen_field *list = group->fields;
451
452      ctx->group = ctx->group->parent;
453
454      while (list && list->end <= 31) {
455         if (list->start >= 16 && list->has_default) {
456            group->opcode_mask |=
457               mask(list->start % 32, list->end % 32);
458            group->opcode |= list->default_value << list->start;
459         }
460         list = list->next;
461      }
462
463      if (strcmp(name, "instruction") == 0)
464         _mesa_hash_table_insert(spec->commands, group->name, group);
465      else if (strcmp(name, "struct") == 0)
466         _mesa_hash_table_insert(spec->structs, group->name, group);
467      else if (strcmp(name, "register") == 0) {
468         _mesa_hash_table_insert(spec->registers_by_name, group->name, group);
469         _mesa_hash_table_insert(spec->registers_by_offset,
470                                 (void *) (uintptr_t) group->register_offset,
471                                 group);
472      }
473   } else if (strcmp(name, "group") == 0) {
474      ctx->group = ctx->group->parent;
475   } else if (strcmp(name, "field") == 0) {
476      struct gen_field *field = ctx->last_field;
477      ctx->last_field = NULL;
478      field->inline_enum.values = ctx->values;
479      field->inline_enum.nvalues = ctx->n_values;
480      ctx->values = ralloc_array(ctx->spec, struct gen_value*, ctx->n_allocated_values = 2);
481      ctx->n_values = 0;
482   } else if (strcmp(name, "enum") == 0) {
483      struct gen_enum *e = ctx->enoom;
484      e->values = ctx->values;
485      e->nvalues = ctx->n_values;
486      ctx->values = ralloc_array(ctx->spec, struct gen_value*, ctx->n_allocated_values = 2);
487      ctx->n_values = 0;
488      ctx->enoom = NULL;
489      _mesa_hash_table_insert(spec->enums, e->name, e);
490   }
491}
492
493static void
494character_data(void *data, const XML_Char *s, int len)
495{
496}
497
498static int
499devinfo_to_gen(const struct gen_device_info *devinfo, bool x10)
500{
501   if (devinfo->is_baytrail || devinfo->is_haswell) {
502      return devinfo->gen * 10 + 5;
503   }
504
505   return x10 ? devinfo->gen * 10 : devinfo->gen;
506}
507
508static uint32_t zlib_inflate(const void *compressed_data,
509                             uint32_t compressed_len,
510                             void **out_ptr)
511{
512   struct z_stream_s zstream;
513   void *out;
514
515   memset(&zstream, 0, sizeof(zstream));
516
517   zstream.next_in = (unsigned char *)compressed_data;
518   zstream.avail_in = compressed_len;
519
520   if (inflateInit(&zstream) != Z_OK)
521      return 0;
522
523   out = malloc(4096);
524   zstream.next_out = out;
525   zstream.avail_out = 4096;
526
527   do {
528      switch (inflate(&zstream, Z_SYNC_FLUSH)) {
529      case Z_STREAM_END:
530         goto end;
531      case Z_OK:
532         break;
533      default:
534         inflateEnd(&zstream);
535         return 0;
536      }
537
538      if (zstream.avail_out)
539         break;
540
541      out = realloc(out, 2*zstream.total_out);
542      if (out == NULL) {
543         inflateEnd(&zstream);
544         return 0;
545      }
546
547      zstream.next_out = (unsigned char *)out + zstream.total_out;
548      zstream.avail_out = zstream.total_out;
549   } while (1);
550 end:
551   inflateEnd(&zstream);
552   *out_ptr = out;
553   return zstream.total_out;
554}
555
556static uint32_t _hash_uint32(const void *key)
557{
558   return (uint32_t) (uintptr_t) key;
559}
560
561static struct gen_spec *
562gen_spec_init(void)
563{
564   struct gen_spec *spec;
565   spec = rzalloc(NULL, struct gen_spec);
566   if (spec == NULL)
567      return NULL;
568
569   spec->commands =
570      _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
571   spec->structs =
572      _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
573   spec->registers_by_name =
574      _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
575   spec->registers_by_offset =
576      _mesa_hash_table_create(spec, _hash_uint32, _mesa_key_pointer_equal);
577   spec->enums =
578      _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
579   spec->access_cache =
580      _mesa_hash_table_create(spec, _mesa_hash_string, _mesa_key_string_equal);
581
582   return spec;
583}
584
585struct gen_spec *
586gen_spec_load(const struct gen_device_info *devinfo)
587{
588   struct parser_context ctx;
589   void *buf;
590   uint8_t *text_data = NULL;
591   uint32_t text_offset = 0, text_length = 0;
592   MAYBE_UNUSED uint32_t total_length;
593   uint32_t gen_10 = devinfo_to_gen(devinfo, true);
594
595   for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) {
596      if (genxml_files_table[i].gen_10 == gen_10) {
597         text_offset = genxml_files_table[i].offset;
598         text_length = genxml_files_table[i].length;
599         break;
600      }
601   }
602
603   if (text_length == 0) {
604      fprintf(stderr, "unable to find gen (%u) data\n", gen_10);
605      return NULL;
606   }
607
608   memset(&ctx, 0, sizeof ctx);
609   ctx.parser = XML_ParserCreate(NULL);
610   XML_SetUserData(ctx.parser, &ctx);
611   if (ctx.parser == NULL) {
612      fprintf(stderr, "failed to create parser\n");
613      return NULL;
614   }
615
616   XML_SetElementHandler(ctx.parser, start_element, end_element);
617   XML_SetCharacterDataHandler(ctx.parser, character_data);
618
619   ctx.spec = gen_spec_init();
620   if (ctx.spec == NULL) {
621      fprintf(stderr, "Failed to create gen_spec\n");
622      return NULL;
623   }
624
625   total_length = zlib_inflate(compress_genxmls,
626                               sizeof(compress_genxmls),
627                               (void **) &text_data);
628   assert(text_offset + text_length <= total_length);
629
630   buf = XML_GetBuffer(ctx.parser, text_length);
631   memcpy(buf, &text_data[text_offset], text_length);
632
633   if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) {
634      fprintf(stderr,
635              "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
636              XML_GetCurrentLineNumber(ctx.parser),
637              XML_GetCurrentColumnNumber(ctx.parser),
638              XML_GetCurrentByteIndex(ctx.parser), text_length,
639              XML_ErrorString(XML_GetErrorCode(ctx.parser)));
640      XML_ParserFree(ctx.parser);
641      free(text_data);
642      return NULL;
643   }
644
645   XML_ParserFree(ctx.parser);
646   free(text_data);
647
648   return ctx.spec;
649}
650
651struct gen_spec *
652gen_spec_load_from_path(const struct gen_device_info *devinfo,
653                        const char *path)
654{
655   struct parser_context ctx;
656   size_t len, filename_len = strlen(path) + 20;
657   char *filename = malloc(filename_len);
658   void *buf;
659   FILE *input;
660
661   len = snprintf(filename, filename_len, "%s/gen%i.xml",
662                  path, devinfo_to_gen(devinfo, false));
663   assert(len < filename_len);
664
665   input = fopen(filename, "r");
666   if (input == NULL) {
667      fprintf(stderr, "failed to open xml description\n");
668      free(filename);
669      return NULL;
670   }
671
672   memset(&ctx, 0, sizeof ctx);
673   ctx.parser = XML_ParserCreate(NULL);
674   XML_SetUserData(ctx.parser, &ctx);
675   if (ctx.parser == NULL) {
676      fprintf(stderr, "failed to create parser\n");
677      fclose(input);
678      free(filename);
679      return NULL;
680   }
681
682   XML_SetElementHandler(ctx.parser, start_element, end_element);
683   XML_SetCharacterDataHandler(ctx.parser, character_data);
684   ctx.loc.filename = filename;
685
686   ctx.spec = gen_spec_init();
687   if (ctx.spec == NULL) {
688      fprintf(stderr, "Failed to create gen_spec\n");
689      goto end;
690   }
691
692   do {
693      buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
694      len = fread(buf, 1, XML_BUFFER_SIZE, input);
695      if (ferror(input)) {
696         fprintf(stderr, "fread: %m\n");
697         gen_spec_destroy(ctx.spec);
698         ctx.spec = NULL;
699         goto end;
700      } else if (feof(input))
701         goto end;
702
703      if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
704         fprintf(stderr,
705                 "Error parsing XML at line %ld col %ld: %s\n",
706                 XML_GetCurrentLineNumber(ctx.parser),
707                 XML_GetCurrentColumnNumber(ctx.parser),
708                 XML_ErrorString(XML_GetErrorCode(ctx.parser)));
709         gen_spec_destroy(ctx.spec);
710         ctx.spec = NULL;
711         goto end;
712      }
713   } while (len > 0);
714
715 end:
716   XML_ParserFree(ctx.parser);
717
718   fclose(input);
719   free(filename);
720
721   /* free ctx.spec if genxml is empty */
722   if (ctx.spec && _mesa_hash_table_num_entries(ctx.spec->commands) == 0) {
723      gen_spec_destroy(ctx.spec);
724      return NULL;
725   }
726
727   return ctx.spec;
728}
729
730void gen_spec_destroy(struct gen_spec *spec)
731{
732   ralloc_free(spec);
733}
734
735struct gen_group *
736gen_spec_find_instruction(struct gen_spec *spec,
737                          enum drm_i915_gem_engine_class engine,
738                          const uint32_t *p)
739{
740   hash_table_foreach(spec->commands, entry) {
741      struct gen_group *command = entry->data;
742      uint32_t opcode = *p & command->opcode_mask;
743      if ((command->engine_mask & I915_ENGINE_CLASS_TO_MASK(engine)) &&
744           opcode == command->opcode)
745         return command;
746   }
747
748   return NULL;
749}
750
751struct gen_field *
752gen_group_find_field(struct gen_group *group, const char *name)
753{
754   char path[256];
755   snprintf(path, sizeof(path), "%s/%s", group->name, name);
756
757   struct gen_spec *spec = group->spec;
758   struct hash_entry *entry = _mesa_hash_table_search(spec->access_cache,
759                                                      path);
760   if (entry)
761      return entry->data;
762
763   struct gen_field *field = group->fields;
764   while (field) {
765      if (strcmp(field->name, name) == 0) {
766         _mesa_hash_table_insert(spec->access_cache,
767                                 ralloc_strdup(spec, path),
768                                 field);
769         return field;
770      }
771      field = field->next;
772   }
773
774   return NULL;
775}
776
777int
778gen_group_get_length(struct gen_group *group, const uint32_t *p)
779{
780   if (group) {
781      if (group->fixed_length)
782         return group->dw_length;
783      else {
784         struct gen_field *field = group->dword_length_field;
785         if (field) {
786            return field_value(p[0], field->start, field->end) + group->bias;
787         }
788      }
789   }
790
791   uint32_t h = p[0];
792   uint32_t type = field_value(h, 29, 31);
793
794   switch (type) {
795   case 0: /* MI */ {
796      uint32_t opcode = field_value(h, 23, 28);
797      if (opcode < 16)
798         return 1;
799      else
800         return field_value(h, 0, 7) + 2;
801      break;
802   }
803
804   case 2: /* BLT */ {
805      return field_value(h, 0, 7) + 2;
806   }
807
808   case 3: /* Render */ {
809      uint32_t subtype = field_value(h, 27, 28);
810      uint32_t opcode = field_value(h, 24, 26);
811      uint16_t whole_opcode = field_value(h, 16, 31);
812      switch (subtype) {
813      case 0:
814         if (whole_opcode == 0x6104 /* PIPELINE_SELECT_965 */)
815            return 1;
816         else if (opcode < 2)
817            return field_value(h, 0, 7) + 2;
818         else
819            return -1;
820      case 1:
821         if (opcode < 2)
822            return 1;
823         else
824            return -1;
825      case 2: {
826         if (opcode == 0)
827            return field_value(h, 0, 7) + 2;
828         else if (opcode < 3)
829            return field_value(h, 0, 15) + 2;
830         else
831            return -1;
832      }
833      case 3:
834         if (whole_opcode == 0x780b)
835            return 1;
836         else if (opcode < 4)
837            return field_value(h, 0, 7) + 2;
838         else
839            return -1;
840      }
841   }
842   }
843
844   return -1;
845}
846
847static const char *
848gen_get_enum_name(struct gen_enum *e, uint64_t value)
849{
850   for (int i = 0; i < e->nvalues; i++) {
851      if (e->values[i]->value == value) {
852         return e->values[i]->name;
853      }
854   }
855   return NULL;
856}
857
858static bool
859iter_more_fields(const struct gen_field_iterator *iter)
860{
861   return iter->field != NULL && iter->field->next != NULL;
862}
863
864static uint32_t
865iter_group_offset_bits(const struct gen_field_iterator *iter,
866                       uint32_t group_iter)
867{
868   return iter->group->group_offset + (group_iter * iter->group->group_size);
869}
870
871static bool
872iter_more_groups(const struct gen_field_iterator *iter)
873{
874   if (iter->group->variable) {
875      int length = gen_group_get_length(iter->group, iter->p);
876      assert(length >= 0 && "error the length is unknown!");
877      return iter_group_offset_bits(iter, iter->group_iter + 1) <
878              (length * 32);
879   } else {
880      return (iter->group_iter + 1) < iter->group->group_count ||
881         iter->group->next != NULL;
882   }
883}
884
885static void
886iter_start_field(struct gen_field_iterator *iter, struct gen_field *field)
887{
888   iter->field = field;
889
890   int group_member_offset = iter_group_offset_bits(iter, iter->group_iter);
891
892   iter->start_bit = group_member_offset + iter->field->start;
893   iter->end_bit = group_member_offset + iter->field->end;
894   iter->struct_desc = NULL;
895}
896
897static void
898iter_advance_group(struct gen_field_iterator *iter)
899{
900   if (iter->group->variable)
901      iter->group_iter++;
902   else {
903      if ((iter->group_iter + 1) < iter->group->group_count) {
904         iter->group_iter++;
905      } else {
906         iter->group = iter->group->next;
907         iter->group_iter = 0;
908      }
909   }
910
911   iter_start_field(iter, iter->group->fields);
912}
913
914static bool
915iter_advance_field(struct gen_field_iterator *iter)
916{
917   if (iter_more_fields(iter)) {
918      iter_start_field(iter, iter->field->next);
919   } else {
920      if (!iter_more_groups(iter))
921         return false;
922
923      iter_advance_group(iter);
924   }
925   return true;
926}
927
928static bool
929iter_decode_field_raw(struct gen_field_iterator *iter, uint64_t *qw)
930{
931   *qw = 0;
932
933   int field_start = iter->p_bit + iter->start_bit;
934   int field_end = iter->p_bit + iter->end_bit;
935
936   const uint32_t *p = iter->p + (iter->start_bit / 32);
937   if (iter->p_end && p >= iter->p_end)
938      return false;
939
940   if ((field_end - field_start) > 32) {
941      if (!iter->p_end || (p + 1) < iter->p_end)
942         *qw = ((uint64_t) p[1]) << 32;
943      *qw |= p[0];
944   } else
945      *qw = p[0];
946
947   *qw = field_value(*qw, field_start, field_end);
948
949   /* Address & offset types have to be aligned to dwords, their start bit is
950    * a reminder of the alignment requirement.
951    */
952   if (iter->field->type.kind == GEN_TYPE_ADDRESS ||
953       iter->field->type.kind == GEN_TYPE_OFFSET)
954      *qw <<= field_start % 32;
955
956   return true;
957}
958
959static bool
960iter_decode_field(struct gen_field_iterator *iter)
961{
962   union {
963      uint64_t qw;
964      float f;
965   } v;
966
967   if (iter->field->name)
968      snprintf(iter->name, sizeof(iter->name), "%s", iter->field->name);
969   else
970      memset(iter->name, 0, sizeof(iter->name));
971
972   memset(&v, 0, sizeof(v));
973
974   if (!iter_decode_field_raw(iter, &iter->raw_value))
975      return false;
976
977   const char *enum_name = NULL;
978
979   v.qw = iter->raw_value;
980   switch (iter->field->type.kind) {
981   case GEN_TYPE_UNKNOWN:
982   case GEN_TYPE_INT: {
983      snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw);
984      enum_name = gen_get_enum_name(&iter->field->inline_enum, v.qw);
985      break;
986   }
987   case GEN_TYPE_UINT: {
988      snprintf(iter->value, sizeof(iter->value), "%"PRIu64, v.qw);
989      enum_name = gen_get_enum_name(&iter->field->inline_enum, v.qw);
990      break;
991   }
992   case GEN_TYPE_BOOL: {
993      const char *true_string =
994         iter->print_colors ? "\e[0;35mtrue\e[0m" : "true";
995      snprintf(iter->value, sizeof(iter->value), "%s",
996               v.qw ? true_string : "false");
997      break;
998   }
999   case GEN_TYPE_FLOAT:
1000      snprintf(iter->value, sizeof(iter->value), "%f", v.f);
1001      break;
1002   case GEN_TYPE_ADDRESS:
1003   case GEN_TYPE_OFFSET:
1004      snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, v.qw);
1005      break;
1006   case GEN_TYPE_STRUCT:
1007      snprintf(iter->value, sizeof(iter->value), "<struct %s>",
1008               iter->field->type.gen_struct->name);
1009      iter->struct_desc =
1010         gen_spec_find_struct(iter->group->spec,
1011                              iter->field->type.gen_struct->name);
1012      break;
1013   case GEN_TYPE_UFIXED:
1014      snprintf(iter->value, sizeof(iter->value), "%f",
1015               (float) v.qw / (1 << iter->field->type.f));
1016      break;
1017   case GEN_TYPE_SFIXED: {
1018      /* Sign extend before converting */
1019      int bits = iter->field->type.i + iter->field->type.f + 1;
1020      int64_t v_sign_extend = ((int64_t)(v.qw << (64 - bits))) >> (64 - bits);
1021      snprintf(iter->value, sizeof(iter->value), "%f",
1022               (float) v_sign_extend / (1 << iter->field->type.f));
1023      break;
1024   }
1025   case GEN_TYPE_MBO:
1026       break;
1027   case GEN_TYPE_ENUM: {
1028      snprintf(iter->value, sizeof(iter->value), "%"PRId64, v.qw);
1029      enum_name = gen_get_enum_name(iter->field->type.gen_enum, v.qw);
1030      break;
1031   }
1032   }
1033
1034   if (strlen(iter->group->name) == 0) {
1035      int length = strlen(iter->name);
1036      snprintf(iter->name + length, sizeof(iter->name) - length,
1037               "[%i]", iter->group_iter);
1038   }
1039
1040   if (enum_name) {
1041      int length = strlen(iter->value);
1042      snprintf(iter->value + length, sizeof(iter->value) - length,
1043               " (%s)", enum_name);
1044   } else if (strcmp(iter->name, "Surface Format") == 0 ||
1045              strcmp(iter->name, "Source Element Format") == 0) {
1046      if (isl_format_is_valid((enum isl_format)v.qw)) {
1047         const char *fmt_name = isl_format_get_name((enum isl_format)v.qw);
1048         int length = strlen(iter->value);
1049         snprintf(iter->value + length, sizeof(iter->value) - length,
1050                  " (%s)", fmt_name);
1051      }
1052   }
1053
1054   return true;
1055}
1056
1057void
1058gen_field_iterator_init(struct gen_field_iterator *iter,
1059                        struct gen_group *group,
1060                        const uint32_t *p, int p_bit,
1061                        bool print_colors)
1062{
1063   memset(iter, 0, sizeof(*iter));
1064
1065   iter->group = group;
1066   iter->p = p;
1067   iter->p_bit = p_bit;
1068
1069   int length = gen_group_get_length(iter->group, iter->p);
1070   assert(length >= 0 && "error the length is unknown!");
1071   iter->p_end = length >= 0 ? &p[length] : NULL;
1072   iter->print_colors = print_colors;
1073}
1074
1075bool
1076gen_field_iterator_next(struct gen_field_iterator *iter)
1077{
1078   /* Initial condition */
1079   if (!iter->field) {
1080      if (iter->group->fields)
1081         iter_start_field(iter, iter->group->fields);
1082      else
1083         iter_start_field(iter, iter->group->next->fields);
1084
1085      bool result = iter_decode_field(iter);
1086      if (!result && iter->p_end) {
1087         /* We're dealing with a non empty struct of length=0 (BLEND_STATE on
1088          * Gen 7.5)
1089          */
1090         assert(iter->group->dw_length == 0);
1091      }
1092
1093      return result;
1094   }
1095
1096   if (!iter_advance_field(iter))
1097      return false;
1098
1099   if (!iter_decode_field(iter))
1100      return false;
1101
1102   return true;
1103}
1104
1105static void
1106print_dword_header(FILE *outfile,
1107                   struct gen_field_iterator *iter,
1108                   uint64_t offset, uint32_t dword)
1109{
1110   fprintf(outfile, "0x%08"PRIx64":  0x%08x : Dword %d\n",
1111           offset + 4 * dword, iter->p[dword], dword);
1112}
1113
1114bool
1115gen_field_is_header(struct gen_field *field)
1116{
1117   uint32_t bits;
1118
1119   if (field->start >= 32)
1120      return false;
1121
1122   bits = (1U << (field->end - field->start + 1)) - 1;
1123   bits <<= field->start;
1124
1125   return (field->parent->opcode_mask & bits) != 0;
1126}
1127
1128void
1129gen_print_group(FILE *outfile, struct gen_group *group, uint64_t offset,
1130                const uint32_t *p, int p_bit, bool color)
1131{
1132   struct gen_field_iterator iter;
1133   int last_dword = -1;
1134
1135   gen_field_iterator_init(&iter, group, p, p_bit, color);
1136   while (gen_field_iterator_next(&iter)) {
1137      int iter_dword = iter.end_bit / 32;
1138      if (last_dword != iter_dword) {
1139         for (int i = last_dword + 1; i <= iter_dword; i++)
1140            print_dword_header(outfile, &iter, offset, i);
1141         last_dword = iter_dword;
1142      }
1143      if (!gen_field_is_header(iter.field)) {
1144         fprintf(outfile, "    %s: %s\n", iter.name, iter.value);
1145         if (iter.struct_desc) {
1146            int struct_dword = iter.start_bit / 32;
1147            uint64_t struct_offset = offset + 4 * struct_dword;
1148            gen_print_group(outfile, iter.struct_desc, struct_offset,
1149                            &p[struct_dword], iter.start_bit % 32, color);
1150         }
1151      }
1152   }
1153}
1154