1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2017 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "common/intel_decoder.h"
25bf215546Sopenharmony_ci#include "intel_disasm.h"
26bf215546Sopenharmony_ci#include "util/macros.h"
27bf215546Sopenharmony_ci#include "util/u_math.h" /* Needed for ROUND_DOWN_TO */
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include <string.h>
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_civoid
32bf215546Sopenharmony_ciintel_batch_decode_ctx_init(struct intel_batch_decode_ctx *ctx,
33bf215546Sopenharmony_ci                            const struct brw_isa_info *isa,
34bf215546Sopenharmony_ci                            const struct intel_device_info *devinfo,
35bf215546Sopenharmony_ci                            FILE *fp, enum intel_batch_decode_flags flags,
36bf215546Sopenharmony_ci                            const char *xml_path,
37bf215546Sopenharmony_ci                            struct intel_batch_decode_bo (*get_bo)(void *,
38bf215546Sopenharmony_ci                                                                   bool,
39bf215546Sopenharmony_ci                                                                   uint64_t),
40bf215546Sopenharmony_ci                            unsigned (*get_state_size)(void *, uint64_t,
41bf215546Sopenharmony_ci                                                       uint64_t),
42bf215546Sopenharmony_ci                            void *user_data)
43bf215546Sopenharmony_ci{
44bf215546Sopenharmony_ci   memset(ctx, 0, sizeof(*ctx));
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   ctx->isa = isa;
47bf215546Sopenharmony_ci   ctx->devinfo = *devinfo;
48bf215546Sopenharmony_ci   ctx->get_bo = get_bo;
49bf215546Sopenharmony_ci   ctx->get_state_size = get_state_size;
50bf215546Sopenharmony_ci   ctx->user_data = user_data;
51bf215546Sopenharmony_ci   ctx->fp = fp;
52bf215546Sopenharmony_ci   ctx->flags = flags;
53bf215546Sopenharmony_ci   ctx->max_vbo_decoded_lines = -1; /* No limit! */
54bf215546Sopenharmony_ci   ctx->engine = I915_ENGINE_CLASS_RENDER;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   if (xml_path == NULL)
57bf215546Sopenharmony_ci      ctx->spec = intel_spec_load(devinfo);
58bf215546Sopenharmony_ci   else
59bf215546Sopenharmony_ci      ctx->spec = intel_spec_load_from_path(devinfo, xml_path);
60bf215546Sopenharmony_ci}
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_civoid
63bf215546Sopenharmony_ciintel_batch_decode_ctx_finish(struct intel_batch_decode_ctx *ctx)
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci   intel_spec_destroy(ctx->spec);
66bf215546Sopenharmony_ci}
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci#define CSI "\e["
69bf215546Sopenharmony_ci#define RED_COLOR    CSI "31m"
70bf215546Sopenharmony_ci#define BLUE_HEADER  CSI "0;44m" CSI "1;37m"
71bf215546Sopenharmony_ci#define GREEN_HEADER CSI "1;42m"
72bf215546Sopenharmony_ci#define NORMAL       CSI "0m"
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_cistatic void
75bf215546Sopenharmony_cictx_print_group(struct intel_batch_decode_ctx *ctx,
76bf215546Sopenharmony_ci                struct intel_group *group,
77bf215546Sopenharmony_ci                uint64_t address, const void *map)
78bf215546Sopenharmony_ci{
79bf215546Sopenharmony_ci   intel_print_group(ctx->fp, group, address, map, 0,
80bf215546Sopenharmony_ci                   (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) != 0);
81bf215546Sopenharmony_ci}
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_cistatic struct intel_batch_decode_bo
84bf215546Sopenharmony_cictx_get_bo(struct intel_batch_decode_ctx *ctx, bool ppgtt, uint64_t addr)
85bf215546Sopenharmony_ci{
86bf215546Sopenharmony_ci   if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0)) {
87bf215546Sopenharmony_ci      /* On Broadwell and above, we have 48-bit addresses which consume two
88bf215546Sopenharmony_ci       * dwords.  Some packets require that these get stored in a "canonical
89bf215546Sopenharmony_ci       * form" which means that bit 47 is sign-extended through the upper
90bf215546Sopenharmony_ci       * bits. In order to correctly handle those aub dumps, we need to mask
91bf215546Sopenharmony_ci       * off the top 16 bits.
92bf215546Sopenharmony_ci       */
93bf215546Sopenharmony_ci      addr &= (~0ull >> 16);
94bf215546Sopenharmony_ci   }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   struct intel_batch_decode_bo bo = ctx->get_bo(ctx->user_data, ppgtt, addr);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   if (intel_spec_get_gen(ctx->spec) >= intel_make_gen(8,0))
99bf215546Sopenharmony_ci      bo.addr &= (~0ull >> 16);
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   /* We may actually have an offset into the bo */
102bf215546Sopenharmony_ci   if (bo.map != NULL) {
103bf215546Sopenharmony_ci      assert(bo.addr <= addr);
104bf215546Sopenharmony_ci      uint64_t offset = addr - bo.addr;
105bf215546Sopenharmony_ci      bo.map += offset;
106bf215546Sopenharmony_ci      bo.addr += offset;
107bf215546Sopenharmony_ci      bo.size -= offset;
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   return bo;
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_cistatic int
114bf215546Sopenharmony_ciupdate_count(struct intel_batch_decode_ctx *ctx,
115bf215546Sopenharmony_ci             uint64_t address,
116bf215546Sopenharmony_ci             uint64_t base_address,
117bf215546Sopenharmony_ci             unsigned element_dwords,
118bf215546Sopenharmony_ci             unsigned guess)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   unsigned size = 0;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   if (ctx->get_state_size)
123bf215546Sopenharmony_ci      size = ctx->get_state_size(ctx->user_data, address, base_address);
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   if (size > 0)
126bf215546Sopenharmony_ci      return size / (sizeof(uint32_t) * element_dwords);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   /* In the absence of any information, just guess arbitrarily. */
129bf215546Sopenharmony_ci   return guess;
130bf215546Sopenharmony_ci}
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_cistatic void
133bf215546Sopenharmony_cictx_disassemble_program(struct intel_batch_decode_ctx *ctx,
134bf215546Sopenharmony_ci                        uint32_t ksp, const char *type)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   uint64_t addr = ctx->instruction_base + ksp;
137bf215546Sopenharmony_ci   struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
138bf215546Sopenharmony_ci   if (!bo.map)
139bf215546Sopenharmony_ci      return;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   fprintf(ctx->fp, "\nReferenced %s:\n", type);
142bf215546Sopenharmony_ci   intel_disassemble(ctx->isa, bo.map, 0, ctx->fp);
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci/* Heuristic to determine whether a uint32_t is probably actually a float
146bf215546Sopenharmony_ci * (http://stackoverflow.com/a/2953466)
147bf215546Sopenharmony_ci */
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_cistatic bool
150bf215546Sopenharmony_ciprobably_float(uint32_t bits)
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci   int exp = ((bits & 0x7f800000U) >> 23) - 127;
153bf215546Sopenharmony_ci   uint32_t mant = bits & 0x007fffff;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   /* +- 0.0 */
156bf215546Sopenharmony_ci   if (exp == -127 && mant == 0)
157bf215546Sopenharmony_ci      return true;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   /* +- 1 billionth to 1 billion */
160bf215546Sopenharmony_ci   if (-30 <= exp && exp <= 30)
161bf215546Sopenharmony_ci      return true;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   /* some value with only a few binary digits */
164bf215546Sopenharmony_ci   if ((mant & 0x0000ffff) == 0)
165bf215546Sopenharmony_ci      return true;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   return false;
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_cistatic void
171bf215546Sopenharmony_cictx_print_buffer(struct intel_batch_decode_ctx *ctx,
172bf215546Sopenharmony_ci                 struct intel_batch_decode_bo bo,
173bf215546Sopenharmony_ci                 uint32_t read_length,
174bf215546Sopenharmony_ci                 uint32_t pitch,
175bf215546Sopenharmony_ci                 int max_lines)
176bf215546Sopenharmony_ci{
177bf215546Sopenharmony_ci   const uint32_t *dw_end =
178bf215546Sopenharmony_ci         bo.map + ROUND_DOWN_TO(MIN2(bo.size, read_length), 4);
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   int column_count = 0, pitch_col_count = 0, line_count = -1;
181bf215546Sopenharmony_ci   for (const uint32_t *dw = bo.map; dw < dw_end; dw++) {
182bf215546Sopenharmony_ci      if (pitch_col_count * 4 == pitch || column_count == 8) {
183bf215546Sopenharmony_ci         fprintf(ctx->fp, "\n");
184bf215546Sopenharmony_ci         column_count = 0;
185bf215546Sopenharmony_ci         if (pitch_col_count * 4 == pitch)
186bf215546Sopenharmony_ci            pitch_col_count = 0;
187bf215546Sopenharmony_ci         line_count++;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci         if (max_lines >= 0 && line_count >= max_lines)
190bf215546Sopenharmony_ci            break;
191bf215546Sopenharmony_ci      }
192bf215546Sopenharmony_ci      fprintf(ctx->fp, column_count == 0 ? "  " : " ");
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci      if ((ctx->flags & INTEL_BATCH_DECODE_FLOATS) && probably_float(*dw))
195bf215546Sopenharmony_ci         fprintf(ctx->fp, "  %8.2f", *(float *) dw);
196bf215546Sopenharmony_ci      else
197bf215546Sopenharmony_ci         fprintf(ctx->fp, "  0x%08x", *dw);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci      column_count++;
200bf215546Sopenharmony_ci      pitch_col_count++;
201bf215546Sopenharmony_ci   }
202bf215546Sopenharmony_ci   fprintf(ctx->fp, "\n");
203bf215546Sopenharmony_ci}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_cistatic struct intel_group *
206bf215546Sopenharmony_ciintel_ctx_find_instruction(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
207bf215546Sopenharmony_ci{
208bf215546Sopenharmony_ci   return intel_spec_find_instruction(ctx->spec, ctx->engine, p);
209bf215546Sopenharmony_ci}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_cistatic void
212bf215546Sopenharmony_cihandle_state_base_address(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   struct intel_field_iterator iter;
217bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   uint64_t surface_base = 0, dynamic_base = 0, instruction_base = 0;
220bf215546Sopenharmony_ci   bool surface_modify = 0, dynamic_modify = 0, instruction_modify = 0;
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
223bf215546Sopenharmony_ci      if (strcmp(iter.name, "Surface State Base Address") == 0) {
224bf215546Sopenharmony_ci         surface_base = iter.raw_value;
225bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Dynamic State Base Address") == 0) {
226bf215546Sopenharmony_ci         dynamic_base = iter.raw_value;
227bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Instruction Base Address") == 0) {
228bf215546Sopenharmony_ci         instruction_base = iter.raw_value;
229bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Surface State Base Address Modify Enable") == 0) {
230bf215546Sopenharmony_ci         surface_modify = iter.raw_value;
231bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Dynamic State Base Address Modify Enable") == 0) {
232bf215546Sopenharmony_ci         dynamic_modify = iter.raw_value;
233bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Instruction Base Address Modify Enable") == 0) {
234bf215546Sopenharmony_ci         instruction_modify = iter.raw_value;
235bf215546Sopenharmony_ci      }
236bf215546Sopenharmony_ci   }
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   if (dynamic_modify)
239bf215546Sopenharmony_ci      ctx->dynamic_base = dynamic_base;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   if (surface_modify)
242bf215546Sopenharmony_ci      ctx->surface_base = surface_base;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   if (instruction_modify)
245bf215546Sopenharmony_ci      ctx->instruction_base = instruction_base;
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_cistatic void
249bf215546Sopenharmony_cihandle_binding_table_pool_alloc(struct intel_batch_decode_ctx *ctx,
250bf215546Sopenharmony_ci                                const uint32_t *p)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   struct intel_field_iterator iter;
255bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   uint64_t bt_pool_base = 0;
258bf215546Sopenharmony_ci   bool bt_pool_enable = false;
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
261bf215546Sopenharmony_ci      if (strcmp(iter.name, "Binding Table Pool Base Address") == 0) {
262bf215546Sopenharmony_ci         bt_pool_base = iter.raw_value;
263bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Binding Table Pool Enable") == 0) {
264bf215546Sopenharmony_ci         bt_pool_enable = iter.raw_value;
265bf215546Sopenharmony_ci      }
266bf215546Sopenharmony_ci   }
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   if (bt_pool_enable || ctx->devinfo.verx10 >= 125) {
269bf215546Sopenharmony_ci      ctx->bt_pool_base = bt_pool_base;
270bf215546Sopenharmony_ci   } else {
271bf215546Sopenharmony_ci      ctx->bt_pool_base = 0;
272bf215546Sopenharmony_ci   }
273bf215546Sopenharmony_ci}
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_cistatic void
276bf215546Sopenharmony_cidump_binding_table(struct intel_batch_decode_ctx *ctx,
277bf215546Sopenharmony_ci                   uint32_t offset, int count)
278bf215546Sopenharmony_ci{
279bf215546Sopenharmony_ci   struct intel_group *strct =
280bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "RENDER_SURFACE_STATE");
281bf215546Sopenharmony_ci   if (strct == NULL) {
282bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find RENDER_SURFACE_STATE info\n");
283bf215546Sopenharmony_ci      return;
284bf215546Sopenharmony_ci   }
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   /* Most platforms use a 16-bit pointer with 32B alignment in bits 15:5. */
287bf215546Sopenharmony_ci   uint32_t btp_alignment = 32;
288bf215546Sopenharmony_ci   uint32_t btp_pointer_bits = 16;
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci   if (ctx->devinfo.verx10 >= 125) {
291bf215546Sopenharmony_ci      /* The pointer is now 21-bit with 32B alignment in bits 20:5. */
292bf215546Sopenharmony_ci      btp_pointer_bits = 21;
293bf215546Sopenharmony_ci   } else if (ctx->use_256B_binding_tables) {
294bf215546Sopenharmony_ci      /* When 256B binding tables are enabled, we have to shift the offset
295bf215546Sopenharmony_ci       * which is stored in bits 15:5 but interpreted as bits 18:8 of the
296bf215546Sopenharmony_ci       * actual offset.  The effective pointer is 19-bit with 256B alignment.
297bf215546Sopenharmony_ci       */
298bf215546Sopenharmony_ci      offset <<= 3;
299bf215546Sopenharmony_ci      btp_pointer_bits = 19;
300bf215546Sopenharmony_ci      btp_alignment = 256;
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   const uint64_t bt_pool_base = ctx->bt_pool_base ? ctx->bt_pool_base :
304bf215546Sopenharmony_ci                                                     ctx->surface_base;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   if (count < 0) {
307bf215546Sopenharmony_ci      count = update_count(ctx, bt_pool_base + offset,
308bf215546Sopenharmony_ci                           bt_pool_base, 1, 8);
309bf215546Sopenharmony_ci   }
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   if (offset % btp_alignment != 0 || offset >= (1u << btp_pointer_bits)) {
312bf215546Sopenharmony_ci      fprintf(ctx->fp, "  invalid binding table pointer\n");
313bf215546Sopenharmony_ci      return;
314bf215546Sopenharmony_ci   }
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
317bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, bt_pool_base + offset);
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
320bf215546Sopenharmony_ci      fprintf(ctx->fp, "  binding table unavailable\n");
321bf215546Sopenharmony_ci      return;
322bf215546Sopenharmony_ci   }
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   const uint32_t *pointers = bind_bo.map;
325bf215546Sopenharmony_ci   for (int i = 0; i < count; i++) {
326bf215546Sopenharmony_ci      if (pointers[i] == 0)
327bf215546Sopenharmony_ci         continue;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci      uint64_t addr = ctx->surface_base + pointers[i];
330bf215546Sopenharmony_ci      struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, addr);
331bf215546Sopenharmony_ci      uint32_t size = strct->dw_length * 4;
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci      if (pointers[i] % 32 != 0 ||
334bf215546Sopenharmony_ci          addr < bo.addr || addr + size >= bo.addr + bo.size) {
335bf215546Sopenharmony_ci         fprintf(ctx->fp, "pointer %u: 0x%08x <not valid>\n", i, pointers[i]);
336bf215546Sopenharmony_ci         continue;
337bf215546Sopenharmony_ci      }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      fprintf(ctx->fp, "pointer %u: 0x%08x\n", i, pointers[i]);
340bf215546Sopenharmony_ci      ctx_print_group(ctx, strct, addr, bo.map + (addr - bo.addr));
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci}
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_cistatic void
345bf215546Sopenharmony_cidump_samplers(struct intel_batch_decode_ctx *ctx, uint32_t offset, int count)
346bf215546Sopenharmony_ci{
347bf215546Sopenharmony_ci   struct intel_group *strct = intel_spec_find_struct(ctx->spec, "SAMPLER_STATE");
348bf215546Sopenharmony_ci   uint64_t state_addr = ctx->dynamic_base + offset;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   assert(count > 0);
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
353bf215546Sopenharmony_ci   const void *state_map = bo.map;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   if (state_map == NULL) {
356bf215546Sopenharmony_ci      fprintf(ctx->fp, "  samplers unavailable\n");
357bf215546Sopenharmony_ci      return;
358bf215546Sopenharmony_ci   }
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   if (offset % 32 != 0) {
361bf215546Sopenharmony_ci      fprintf(ctx->fp, "  invalid sampler state pointer\n");
362bf215546Sopenharmony_ci      return;
363bf215546Sopenharmony_ci   }
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   const unsigned sampler_state_size = strct->dw_length * 4;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   if (count * sampler_state_size >= bo.size) {
368bf215546Sopenharmony_ci      fprintf(ctx->fp, "  sampler state ends after bo ends\n");
369bf215546Sopenharmony_ci      assert(!"sampler state ends after bo ends");
370bf215546Sopenharmony_ci      return;
371bf215546Sopenharmony_ci   }
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   for (int i = 0; i < count; i++) {
374bf215546Sopenharmony_ci      fprintf(ctx->fp, "sampler state %d\n", i);
375bf215546Sopenharmony_ci      ctx_print_group(ctx, strct, state_addr, state_map);
376bf215546Sopenharmony_ci      state_addr += sampler_state_size;
377bf215546Sopenharmony_ci      state_map += sampler_state_size;
378bf215546Sopenharmony_ci   }
379bf215546Sopenharmony_ci}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_cistatic void
382bf215546Sopenharmony_cihandle_interface_descriptor_data(struct intel_batch_decode_ctx *ctx,
383bf215546Sopenharmony_ci                                 struct intel_group *desc, const uint32_t *p)
384bf215546Sopenharmony_ci{
385bf215546Sopenharmony_ci   uint64_t ksp = 0;
386bf215546Sopenharmony_ci   uint32_t sampler_offset = 0, sampler_count = 0;
387bf215546Sopenharmony_ci   uint32_t binding_table_offset = 0, binding_entry_count = 0;
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   struct intel_field_iterator iter;
390bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, desc, p, 0, false);
391bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
392bf215546Sopenharmony_ci      if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
393bf215546Sopenharmony_ci         ksp = strtoll(iter.value, NULL, 16);
394bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Sampler State Pointer") == 0) {
395bf215546Sopenharmony_ci         sampler_offset = strtol(iter.value, NULL, 16);
396bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Sampler Count") == 0) {
397bf215546Sopenharmony_ci         sampler_count = strtol(iter.value, NULL, 10);
398bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Binding Table Pointer") == 0) {
399bf215546Sopenharmony_ci         binding_table_offset = strtol(iter.value, NULL, 16);
400bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Binding Table Entry Count") == 0) {
401bf215546Sopenharmony_ci         binding_entry_count = strtol(iter.value, NULL, 10);
402bf215546Sopenharmony_ci      }
403bf215546Sopenharmony_ci   }
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   ctx_disassemble_program(ctx, ksp, "compute shader");
406bf215546Sopenharmony_ci   fprintf(ctx->fp, "\n");
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci   if (sampler_count)
409bf215546Sopenharmony_ci      dump_samplers(ctx, sampler_offset, sampler_count);
410bf215546Sopenharmony_ci   if (binding_entry_count)
411bf215546Sopenharmony_ci      dump_binding_table(ctx, binding_table_offset, binding_entry_count);
412bf215546Sopenharmony_ci}
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_cistatic void
415bf215546Sopenharmony_cihandle_media_interface_descriptor_load(struct intel_batch_decode_ctx *ctx,
416bf215546Sopenharmony_ci                                       const uint32_t *p)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
419bf215546Sopenharmony_ci   struct intel_group *desc =
420bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "INTERFACE_DESCRIPTOR_DATA");
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   struct intel_field_iterator iter;
423bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
424bf215546Sopenharmony_ci   uint32_t descriptor_offset = 0;
425bf215546Sopenharmony_ci   int descriptor_count = 0;
426bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
427bf215546Sopenharmony_ci      if (strcmp(iter.name, "Interface Descriptor Data Start Address") == 0) {
428bf215546Sopenharmony_ci         descriptor_offset = strtol(iter.value, NULL, 16);
429bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Interface Descriptor Total Length") == 0) {
430bf215546Sopenharmony_ci         descriptor_count =
431bf215546Sopenharmony_ci            strtol(iter.value, NULL, 16) / (desc->dw_length * 4);
432bf215546Sopenharmony_ci      }
433bf215546Sopenharmony_ci   }
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   uint64_t desc_addr = ctx->dynamic_base + descriptor_offset;
436bf215546Sopenharmony_ci   struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, desc_addr);
437bf215546Sopenharmony_ci   const void *desc_map = bo.map;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci   if (desc_map == NULL) {
440bf215546Sopenharmony_ci      fprintf(ctx->fp, "  interface descriptors unavailable\n");
441bf215546Sopenharmony_ci      return;
442bf215546Sopenharmony_ci   }
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   for (int i = 0; i < descriptor_count; i++) {
445bf215546Sopenharmony_ci      fprintf(ctx->fp, "descriptor %d: %08x\n", i, descriptor_offset);
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci      ctx_print_group(ctx, desc, desc_addr, desc_map);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      handle_interface_descriptor_data(ctx, desc, desc_map);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci      desc_map += desc->dw_length;
452bf215546Sopenharmony_ci      desc_addr += desc->dw_length * 4;
453bf215546Sopenharmony_ci   }
454bf215546Sopenharmony_ci}
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_cistatic void
457bf215546Sopenharmony_cihandle_compute_walker(struct intel_batch_decode_ctx *ctx,
458bf215546Sopenharmony_ci                      const uint32_t *p)
459bf215546Sopenharmony_ci{
460bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   struct intel_field_iterator iter;
463bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
464bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
465bf215546Sopenharmony_ci      if (strcmp(iter.name, "Interface Descriptor") == 0) {
466bf215546Sopenharmony_ci         handle_interface_descriptor_data(ctx, iter.struct_desc,
467bf215546Sopenharmony_ci                                          &iter.p[iter.start_bit / 32]);
468bf215546Sopenharmony_ci      }
469bf215546Sopenharmony_ci   }
470bf215546Sopenharmony_ci}
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_cistatic void
473bf215546Sopenharmony_cihandle_3dstate_vertex_buffers(struct intel_batch_decode_ctx *ctx,
474bf215546Sopenharmony_ci                              const uint32_t *p)
475bf215546Sopenharmony_ci{
476bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
477bf215546Sopenharmony_ci   struct intel_group *vbs = intel_spec_find_struct(ctx->spec, "VERTEX_BUFFER_STATE");
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   struct intel_batch_decode_bo vb = {};
480bf215546Sopenharmony_ci   uint32_t vb_size = 0;
481bf215546Sopenharmony_ci   int index = -1;
482bf215546Sopenharmony_ci   int pitch = -1;
483bf215546Sopenharmony_ci   bool ready = false;
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   struct intel_field_iterator iter;
486bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
487bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
488bf215546Sopenharmony_ci      if (iter.struct_desc != vbs)
489bf215546Sopenharmony_ci         continue;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci      struct intel_field_iterator vbs_iter;
492bf215546Sopenharmony_ci      intel_field_iterator_init(&vbs_iter, vbs, &iter.p[iter.start_bit / 32], 0, false);
493bf215546Sopenharmony_ci      while (intel_field_iterator_next(&vbs_iter)) {
494bf215546Sopenharmony_ci         if (strcmp(vbs_iter.name, "Vertex Buffer Index") == 0) {
495bf215546Sopenharmony_ci            index = vbs_iter.raw_value;
496bf215546Sopenharmony_ci         } else if (strcmp(vbs_iter.name, "Buffer Pitch") == 0) {
497bf215546Sopenharmony_ci            pitch = vbs_iter.raw_value;
498bf215546Sopenharmony_ci         } else if (strcmp(vbs_iter.name, "Buffer Starting Address") == 0) {
499bf215546Sopenharmony_ci            vb = ctx_get_bo(ctx, true, vbs_iter.raw_value);
500bf215546Sopenharmony_ci         } else if (strcmp(vbs_iter.name, "Buffer Size") == 0) {
501bf215546Sopenharmony_ci            vb_size = vbs_iter.raw_value;
502bf215546Sopenharmony_ci            ready = true;
503bf215546Sopenharmony_ci         } else if (strcmp(vbs_iter.name, "End Address") == 0) {
504bf215546Sopenharmony_ci            if (vb.map && vbs_iter.raw_value >= vb.addr)
505bf215546Sopenharmony_ci               vb_size = (vbs_iter.raw_value + 1) - vb.addr;
506bf215546Sopenharmony_ci            else
507bf215546Sopenharmony_ci               vb_size = 0;
508bf215546Sopenharmony_ci            ready = true;
509bf215546Sopenharmony_ci         }
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci         if (!ready)
512bf215546Sopenharmony_ci            continue;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci         fprintf(ctx->fp, "vertex buffer %d, size %d\n", index, vb_size);
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci         if (vb.map == NULL) {
517bf215546Sopenharmony_ci            fprintf(ctx->fp, "  buffer contents unavailable\n");
518bf215546Sopenharmony_ci            continue;
519bf215546Sopenharmony_ci         }
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci         if (vb.map == 0 || vb_size == 0)
522bf215546Sopenharmony_ci            continue;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci         ctx_print_buffer(ctx, vb, vb_size, pitch, ctx->max_vbo_decoded_lines);
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci         vb.map = NULL;
527bf215546Sopenharmony_ci         vb_size = 0;
528bf215546Sopenharmony_ci         index = -1;
529bf215546Sopenharmony_ci         pitch = -1;
530bf215546Sopenharmony_ci         ready = false;
531bf215546Sopenharmony_ci      }
532bf215546Sopenharmony_ci   }
533bf215546Sopenharmony_ci}
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_cistatic void
536bf215546Sopenharmony_cihandle_3dstate_index_buffer(struct intel_batch_decode_ctx *ctx,
537bf215546Sopenharmony_ci                            const uint32_t *p)
538bf215546Sopenharmony_ci{
539bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   struct intel_batch_decode_bo ib = {};
542bf215546Sopenharmony_ci   uint32_t ib_size = 0;
543bf215546Sopenharmony_ci   uint32_t format = 0;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci   struct intel_field_iterator iter;
546bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
547bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
548bf215546Sopenharmony_ci      if (strcmp(iter.name, "Index Format") == 0) {
549bf215546Sopenharmony_ci         format = iter.raw_value;
550bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Buffer Starting Address") == 0) {
551bf215546Sopenharmony_ci         ib = ctx_get_bo(ctx, true, iter.raw_value);
552bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Buffer Size") == 0) {
553bf215546Sopenharmony_ci         ib_size = iter.raw_value;
554bf215546Sopenharmony_ci      }
555bf215546Sopenharmony_ci   }
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci   if (ib.map == NULL) {
558bf215546Sopenharmony_ci      fprintf(ctx->fp, "  buffer contents unavailable\n");
559bf215546Sopenharmony_ci      return;
560bf215546Sopenharmony_ci   }
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci   const void *m = ib.map;
563bf215546Sopenharmony_ci   const void *ib_end = ib.map + MIN2(ib.size, ib_size);
564bf215546Sopenharmony_ci   for (int i = 0; m < ib_end && i < 10; i++) {
565bf215546Sopenharmony_ci      switch (format) {
566bf215546Sopenharmony_ci      case 0:
567bf215546Sopenharmony_ci         fprintf(ctx->fp, "%3d ", *(uint8_t *)m);
568bf215546Sopenharmony_ci         m += 1;
569bf215546Sopenharmony_ci         break;
570bf215546Sopenharmony_ci      case 1:
571bf215546Sopenharmony_ci         fprintf(ctx->fp, "%3d ", *(uint16_t *)m);
572bf215546Sopenharmony_ci         m += 2;
573bf215546Sopenharmony_ci         break;
574bf215546Sopenharmony_ci      case 2:
575bf215546Sopenharmony_ci         fprintf(ctx->fp, "%3d ", *(uint32_t *)m);
576bf215546Sopenharmony_ci         m += 4;
577bf215546Sopenharmony_ci         break;
578bf215546Sopenharmony_ci      }
579bf215546Sopenharmony_ci   }
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   if (m < ib_end)
582bf215546Sopenharmony_ci      fprintf(ctx->fp, "...");
583bf215546Sopenharmony_ci   fprintf(ctx->fp, "\n");
584bf215546Sopenharmony_ci}
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_cistatic void
587bf215546Sopenharmony_cidecode_single_ksp(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
588bf215546Sopenharmony_ci{
589bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   uint64_t ksp = 0;
592bf215546Sopenharmony_ci   bool is_simd8 = ctx->devinfo.ver >= 11; /* vertex shaders on Gfx8+ only */
593bf215546Sopenharmony_ci   bool is_enabled = true;
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci   struct intel_field_iterator iter;
596bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
597bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
598bf215546Sopenharmony_ci      if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
599bf215546Sopenharmony_ci         ksp = iter.raw_value;
600bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "SIMD8 Dispatch Enable") == 0) {
601bf215546Sopenharmony_ci         is_simd8 = iter.raw_value;
602bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Dispatch Mode") == 0) {
603bf215546Sopenharmony_ci         is_simd8 = strcmp(iter.value, "SIMD8") == 0;
604bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Dispatch Enable") == 0) {
605bf215546Sopenharmony_ci         is_simd8 = strcmp(iter.value, "SIMD8") == 0;
606bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Enable") == 0) {
607bf215546Sopenharmony_ci         is_enabled = iter.raw_value;
608bf215546Sopenharmony_ci      }
609bf215546Sopenharmony_ci   }
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci   const char *type =
612bf215546Sopenharmony_ci      strcmp(inst->name,   "VS_STATE") == 0 ? "vertex shader" :
613bf215546Sopenharmony_ci      strcmp(inst->name,   "GS_STATE") == 0 ? "geometry shader" :
614bf215546Sopenharmony_ci      strcmp(inst->name,   "SF_STATE") == 0 ? "strips and fans shader" :
615bf215546Sopenharmony_ci      strcmp(inst->name, "CLIP_STATE") == 0 ? "clip shader" :
616bf215546Sopenharmony_ci      strcmp(inst->name, "3DSTATE_DS") == 0 ? "tessellation evaluation shader" :
617bf215546Sopenharmony_ci      strcmp(inst->name, "3DSTATE_HS") == 0 ? "tessellation control shader" :
618bf215546Sopenharmony_ci      strcmp(inst->name, "3DSTATE_VS") == 0 ? (is_simd8 ? "SIMD8 vertex shader" : "vec4 vertex shader") :
619bf215546Sopenharmony_ci      strcmp(inst->name, "3DSTATE_GS") == 0 ? (is_simd8 ? "SIMD8 geometry shader" : "vec4 geometry shader") :
620bf215546Sopenharmony_ci      NULL;
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   if (is_enabled) {
623bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp, type);
624bf215546Sopenharmony_ci      fprintf(ctx->fp, "\n");
625bf215546Sopenharmony_ci   }
626bf215546Sopenharmony_ci}
627bf215546Sopenharmony_ci
628bf215546Sopenharmony_cistatic void
629bf215546Sopenharmony_cidecode_mesh_task_ksp(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
630bf215546Sopenharmony_ci{
631bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   uint64_t ksp = 0;
634bf215546Sopenharmony_ci   uint64_t local_x_maximum = 0;
635bf215546Sopenharmony_ci   uint64_t threads = 0;
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci   struct intel_field_iterator iter;
638bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
639bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
640bf215546Sopenharmony_ci      if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
641bf215546Sopenharmony_ci         ksp = iter.raw_value;
642bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Local X Maximum") == 0) {
643bf215546Sopenharmony_ci         local_x_maximum = iter.raw_value;
644bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Number of Threads in GPGPU Thread Group") == 0) {
645bf215546Sopenharmony_ci         threads = iter.raw_value;
646bf215546Sopenharmony_ci      }
647bf215546Sopenharmony_ci   }
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci   const char *type =
650bf215546Sopenharmony_ci      strcmp(inst->name,   "3DSTATE_MESH_SHADER") == 0 ? "mesh shader" :
651bf215546Sopenharmony_ci      strcmp(inst->name,   "3DSTATE_TASK_SHADER") == 0 ? "task shader" :
652bf215546Sopenharmony_ci      NULL;
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci   if (threads && local_x_maximum) {
655bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp, type);
656bf215546Sopenharmony_ci      fprintf(ctx->fp, "\n");
657bf215546Sopenharmony_ci   }
658bf215546Sopenharmony_ci}
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_cistatic void
661bf215546Sopenharmony_cidecode_ps_kern(struct intel_batch_decode_ctx *ctx,
662bf215546Sopenharmony_ci               struct intel_group *inst, const uint32_t *p)
663bf215546Sopenharmony_ci{
664bf215546Sopenharmony_ci   bool single_ksp = ctx->devinfo.ver == 4;
665bf215546Sopenharmony_ci   uint64_t ksp[3] = {0, 0, 0};
666bf215546Sopenharmony_ci   bool enabled[3] = {false, false, false};
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   struct intel_field_iterator iter;
669bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
670bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
671bf215546Sopenharmony_ci      if (strncmp(iter.name, "Kernel Start Pointer ",
672bf215546Sopenharmony_ci                  strlen("Kernel Start Pointer ")) == 0) {
673bf215546Sopenharmony_ci         int idx = iter.name[strlen("Kernel Start Pointer ")] - '0';
674bf215546Sopenharmony_ci         ksp[idx] = strtol(iter.value, NULL, 16);
675bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "8 Pixel Dispatch Enable") == 0) {
676bf215546Sopenharmony_ci         enabled[0] = strcmp(iter.value, "true") == 0;
677bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "16 Pixel Dispatch Enable") == 0) {
678bf215546Sopenharmony_ci         enabled[1] = strcmp(iter.value, "true") == 0;
679bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "32 Pixel Dispatch Enable") == 0) {
680bf215546Sopenharmony_ci         enabled[2] = strcmp(iter.value, "true") == 0;
681bf215546Sopenharmony_ci      }
682bf215546Sopenharmony_ci   }
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci   if (single_ksp)
685bf215546Sopenharmony_ci      ksp[1] = ksp[2] = ksp[0];
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci   /* Reorder KSPs to be [8, 16, 32] instead of the hardware order. */
688bf215546Sopenharmony_ci   if (enabled[0] + enabled[1] + enabled[2] == 1) {
689bf215546Sopenharmony_ci      if (enabled[1]) {
690bf215546Sopenharmony_ci         ksp[1] = ksp[0];
691bf215546Sopenharmony_ci         ksp[0] = 0;
692bf215546Sopenharmony_ci      } else if (enabled[2]) {
693bf215546Sopenharmony_ci         ksp[2] = ksp[0];
694bf215546Sopenharmony_ci         ksp[0] = 0;
695bf215546Sopenharmony_ci      }
696bf215546Sopenharmony_ci   } else {
697bf215546Sopenharmony_ci      uint64_t tmp = ksp[1];
698bf215546Sopenharmony_ci      ksp[1] = ksp[2];
699bf215546Sopenharmony_ci      ksp[2] = tmp;
700bf215546Sopenharmony_ci   }
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci   if (enabled[0])
703bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp[0], "SIMD8 fragment shader");
704bf215546Sopenharmony_ci   if (enabled[1])
705bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp[1], "SIMD16 fragment shader");
706bf215546Sopenharmony_ci   if (enabled[2])
707bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp[2], "SIMD32 fragment shader");
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   if (enabled[0] || enabled[1] || enabled[2])
710bf215546Sopenharmony_ci      fprintf(ctx->fp, "\n");
711bf215546Sopenharmony_ci}
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_cistatic void
714bf215546Sopenharmony_cidecode_ps_kernels(struct intel_batch_decode_ctx *ctx,
715bf215546Sopenharmony_ci                  const uint32_t *p)
716bf215546Sopenharmony_ci{
717bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
718bf215546Sopenharmony_ci   decode_ps_kern(ctx, inst, p);
719bf215546Sopenharmony_ci}
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_cistatic void
722bf215546Sopenharmony_cidecode_3dstate_constant_all(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
723bf215546Sopenharmony_ci{
724bf215546Sopenharmony_ci   struct intel_group *inst =
725bf215546Sopenharmony_ci      intel_spec_find_instruction(ctx->spec, ctx->engine, p);
726bf215546Sopenharmony_ci   struct intel_group *body =
727bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_ALL_DATA");
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   uint32_t read_length[4] = {0};
730bf215546Sopenharmony_ci   struct intel_batch_decode_bo buffer[4];
731bf215546Sopenharmony_ci   memset(buffer, 0, sizeof(buffer));
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   struct intel_field_iterator outer;
734bf215546Sopenharmony_ci   intel_field_iterator_init(&outer, inst, p, 0, false);
735bf215546Sopenharmony_ci   int idx = 0;
736bf215546Sopenharmony_ci   while (intel_field_iterator_next(&outer)) {
737bf215546Sopenharmony_ci      if (outer.struct_desc != body)
738bf215546Sopenharmony_ci         continue;
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci      struct intel_field_iterator iter;
741bf215546Sopenharmony_ci      intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
742bf215546Sopenharmony_ci                              0, false);
743bf215546Sopenharmony_ci      while (intel_field_iterator_next(&iter)) {
744bf215546Sopenharmony_ci         if (!strcmp(iter.name, "Pointer To Constant Buffer")) {
745bf215546Sopenharmony_ci            buffer[idx] = ctx_get_bo(ctx, true, iter.raw_value);
746bf215546Sopenharmony_ci         } else if (!strcmp(iter.name, "Constant Buffer Read Length")) {
747bf215546Sopenharmony_ci            read_length[idx] = iter.raw_value;
748bf215546Sopenharmony_ci         }
749bf215546Sopenharmony_ci      }
750bf215546Sopenharmony_ci      idx++;
751bf215546Sopenharmony_ci   }
752bf215546Sopenharmony_ci
753bf215546Sopenharmony_ci   for (int i = 0; i < 4; i++) {
754bf215546Sopenharmony_ci      if (read_length[i] == 0 || buffer[i].map == NULL)
755bf215546Sopenharmony_ci         continue;
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci      unsigned size = read_length[i] * 32;
758bf215546Sopenharmony_ci      fprintf(ctx->fp, "constant buffer %d, size %u\n", i, size);
759bf215546Sopenharmony_ci
760bf215546Sopenharmony_ci      ctx_print_buffer(ctx, buffer[i], size, 0, -1);
761bf215546Sopenharmony_ci   }
762bf215546Sopenharmony_ci}
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_cistatic void
765bf215546Sopenharmony_cidecode_3dstate_constant(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
766bf215546Sopenharmony_ci{
767bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
768bf215546Sopenharmony_ci   struct intel_group *body =
769bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "3DSTATE_CONSTANT_BODY");
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   uint32_t read_length[4] = {0};
772bf215546Sopenharmony_ci   uint64_t read_addr[4] = {0};
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_ci   struct intel_field_iterator outer;
775bf215546Sopenharmony_ci   intel_field_iterator_init(&outer, inst, p, 0, false);
776bf215546Sopenharmony_ci   while (intel_field_iterator_next(&outer)) {
777bf215546Sopenharmony_ci      if (outer.struct_desc != body)
778bf215546Sopenharmony_ci         continue;
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci      struct intel_field_iterator iter;
781bf215546Sopenharmony_ci      intel_field_iterator_init(&iter, body, &outer.p[outer.start_bit / 32],
782bf215546Sopenharmony_ci                              0, false);
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci      while (intel_field_iterator_next(&iter)) {
785bf215546Sopenharmony_ci         int idx;
786bf215546Sopenharmony_ci         if (sscanf(iter.name, "Read Length[%d]", &idx) == 1) {
787bf215546Sopenharmony_ci            read_length[idx] = iter.raw_value;
788bf215546Sopenharmony_ci         } else if (sscanf(iter.name, "Buffer[%d]", &idx) == 1) {
789bf215546Sopenharmony_ci            read_addr[idx] = iter.raw_value;
790bf215546Sopenharmony_ci         }
791bf215546Sopenharmony_ci      }
792bf215546Sopenharmony_ci
793bf215546Sopenharmony_ci      for (int i = 0; i < 4; i++) {
794bf215546Sopenharmony_ci         if (read_length[i] == 0)
795bf215546Sopenharmony_ci            continue;
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci         struct intel_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr[i]);
798bf215546Sopenharmony_ci         if (!buffer.map) {
799bf215546Sopenharmony_ci            fprintf(ctx->fp, "constant buffer %d unavailable\n", i);
800bf215546Sopenharmony_ci            continue;
801bf215546Sopenharmony_ci         }
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci         unsigned size = read_length[i] * 32;
804bf215546Sopenharmony_ci         fprintf(ctx->fp, "constant buffer %d, size %u\n", i, size);
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci         ctx_print_buffer(ctx, buffer, size, 0, -1);
807bf215546Sopenharmony_ci      }
808bf215546Sopenharmony_ci   }
809bf215546Sopenharmony_ci}
810bf215546Sopenharmony_ci
811bf215546Sopenharmony_cistatic void
812bf215546Sopenharmony_cidecode_gfx4_constant_buffer(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
813bf215546Sopenharmony_ci{
814bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
815bf215546Sopenharmony_ci   uint64_t read_length = 0, read_addr = 0, valid = 0;
816bf215546Sopenharmony_ci   struct intel_field_iterator iter;
817bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
820bf215546Sopenharmony_ci      if (!strcmp(iter.name, "Buffer Length")) {
821bf215546Sopenharmony_ci         read_length = iter.raw_value;
822bf215546Sopenharmony_ci      } else if (!strcmp(iter.name, "Valid")) {
823bf215546Sopenharmony_ci         valid = iter.raw_value;
824bf215546Sopenharmony_ci      } else if (!strcmp(iter.name, "Buffer Starting Address")) {
825bf215546Sopenharmony_ci         read_addr = iter.raw_value;
826bf215546Sopenharmony_ci      }
827bf215546Sopenharmony_ci   }
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci   if (!valid)
830bf215546Sopenharmony_ci      return;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci   struct intel_batch_decode_bo buffer = ctx_get_bo(ctx, true, read_addr);
833bf215546Sopenharmony_ci   if (!buffer.map) {
834bf215546Sopenharmony_ci      fprintf(ctx->fp, "constant buffer unavailable\n");
835bf215546Sopenharmony_ci      return;
836bf215546Sopenharmony_ci   }
837bf215546Sopenharmony_ci   unsigned size = (read_length + 1) * 16 * sizeof(float);
838bf215546Sopenharmony_ci   fprintf(ctx->fp, "constant buffer size %u\n", size);
839bf215546Sopenharmony_ci
840bf215546Sopenharmony_ci   ctx_print_buffer(ctx, buffer, size, 0, -1);
841bf215546Sopenharmony_ci}
842bf215546Sopenharmony_ci
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_cistatic void
845bf215546Sopenharmony_cidecode_gfx4_3dstate_binding_table_pointers(struct intel_batch_decode_ctx *ctx,
846bf215546Sopenharmony_ci                                           const uint32_t *p)
847bf215546Sopenharmony_ci{
848bf215546Sopenharmony_ci   fprintf(ctx->fp, "VS Binding Table:\n");
849bf215546Sopenharmony_ci   dump_binding_table(ctx, p[1], -1);
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci   fprintf(ctx->fp, "GS Binding Table:\n");
852bf215546Sopenharmony_ci   dump_binding_table(ctx, p[2], -1);
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   if (ctx->devinfo.ver < 6) {
855bf215546Sopenharmony_ci      fprintf(ctx->fp, "CLIP Binding Table:\n");
856bf215546Sopenharmony_ci      dump_binding_table(ctx, p[3], -1);
857bf215546Sopenharmony_ci      fprintf(ctx->fp, "SF Binding Table:\n");
858bf215546Sopenharmony_ci      dump_binding_table(ctx, p[4], -1);
859bf215546Sopenharmony_ci      fprintf(ctx->fp, "PS Binding Table:\n");
860bf215546Sopenharmony_ci      dump_binding_table(ctx, p[5], -1);
861bf215546Sopenharmony_ci   } else {
862bf215546Sopenharmony_ci      fprintf(ctx->fp, "PS Binding Table:\n");
863bf215546Sopenharmony_ci      dump_binding_table(ctx, p[3], -1);
864bf215546Sopenharmony_ci   }
865bf215546Sopenharmony_ci}
866bf215546Sopenharmony_ci
867bf215546Sopenharmony_cistatic void
868bf215546Sopenharmony_cidecode_3dstate_binding_table_pointers(struct intel_batch_decode_ctx *ctx,
869bf215546Sopenharmony_ci                                      const uint32_t *p)
870bf215546Sopenharmony_ci{
871bf215546Sopenharmony_ci   dump_binding_table(ctx, p[1], -1);
872bf215546Sopenharmony_ci}
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_cistatic void
875bf215546Sopenharmony_cidecode_3dstate_sampler_state_pointers(struct intel_batch_decode_ctx *ctx,
876bf215546Sopenharmony_ci                                      const uint32_t *p)
877bf215546Sopenharmony_ci{
878bf215546Sopenharmony_ci   dump_samplers(ctx, p[1], 1);
879bf215546Sopenharmony_ci}
880bf215546Sopenharmony_ci
881bf215546Sopenharmony_cistatic void
882bf215546Sopenharmony_cidecode_3dstate_sampler_state_pointers_gfx6(struct intel_batch_decode_ctx *ctx,
883bf215546Sopenharmony_ci                                           const uint32_t *p)
884bf215546Sopenharmony_ci{
885bf215546Sopenharmony_ci   dump_samplers(ctx, p[1], 1);
886bf215546Sopenharmony_ci   dump_samplers(ctx, p[2], 1);
887bf215546Sopenharmony_ci   dump_samplers(ctx, p[3], 1);
888bf215546Sopenharmony_ci}
889bf215546Sopenharmony_ci
890bf215546Sopenharmony_cistatic bool
891bf215546Sopenharmony_cistr_ends_with(const char *str, const char *end)
892bf215546Sopenharmony_ci{
893bf215546Sopenharmony_ci   int offset = strlen(str) - strlen(end);
894bf215546Sopenharmony_ci   if (offset < 0)
895bf215546Sopenharmony_ci      return false;
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_ci   return strcmp(str + offset, end) == 0;
898bf215546Sopenharmony_ci}
899bf215546Sopenharmony_ci
900bf215546Sopenharmony_cistatic void
901bf215546Sopenharmony_cidecode_dynamic_state(struct intel_batch_decode_ctx *ctx,
902bf215546Sopenharmony_ci                       const char *struct_type, uint32_t state_offset,
903bf215546Sopenharmony_ci                       int count)
904bf215546Sopenharmony_ci{
905bf215546Sopenharmony_ci   uint64_t state_addr = ctx->dynamic_base + state_offset;
906bf215546Sopenharmony_ci   struct intel_batch_decode_bo bo = ctx_get_bo(ctx, true, state_addr);
907bf215546Sopenharmony_ci   const void *state_map = bo.map;
908bf215546Sopenharmony_ci
909bf215546Sopenharmony_ci   if (state_map == NULL) {
910bf215546Sopenharmony_ci      fprintf(ctx->fp, "  dynamic %s state unavailable\n", struct_type);
911bf215546Sopenharmony_ci      return;
912bf215546Sopenharmony_ci   }
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_ci   struct intel_group *state = intel_spec_find_struct(ctx->spec, struct_type);
915bf215546Sopenharmony_ci   if (strcmp(struct_type, "BLEND_STATE") == 0) {
916bf215546Sopenharmony_ci      /* Blend states are different from the others because they have a header
917bf215546Sopenharmony_ci       * struct called BLEND_STATE which is followed by a variable number of
918bf215546Sopenharmony_ci       * BLEND_STATE_ENTRY structs.
919bf215546Sopenharmony_ci       */
920bf215546Sopenharmony_ci      fprintf(ctx->fp, "%s\n", struct_type);
921bf215546Sopenharmony_ci      ctx_print_group(ctx, state, state_addr, state_map);
922bf215546Sopenharmony_ci
923bf215546Sopenharmony_ci      state_addr += state->dw_length * 4;
924bf215546Sopenharmony_ci      state_map += state->dw_length * 4;
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ci      struct_type = "BLEND_STATE_ENTRY";
927bf215546Sopenharmony_ci      state = intel_spec_find_struct(ctx->spec, struct_type);
928bf215546Sopenharmony_ci   }
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci   count = update_count(ctx, ctx->dynamic_base + state_offset,
931bf215546Sopenharmony_ci                        ctx->dynamic_base, state->dw_length, count);
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_ci   for (int i = 0; i < count; i++) {
934bf215546Sopenharmony_ci      fprintf(ctx->fp, "%s %d\n", struct_type, i);
935bf215546Sopenharmony_ci      ctx_print_group(ctx, state, state_addr, state_map);
936bf215546Sopenharmony_ci
937bf215546Sopenharmony_ci      state_addr += state->dw_length * 4;
938bf215546Sopenharmony_ci      state_map += state->dw_length * 4;
939bf215546Sopenharmony_ci   }
940bf215546Sopenharmony_ci}
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_cistatic void
943bf215546Sopenharmony_cidecode_dynamic_state_pointers(struct intel_batch_decode_ctx *ctx,
944bf215546Sopenharmony_ci                              const char *struct_type, const uint32_t *p,
945bf215546Sopenharmony_ci                              int count)
946bf215546Sopenharmony_ci{
947bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
948bf215546Sopenharmony_ci
949bf215546Sopenharmony_ci   uint32_t state_offset = 0;
950bf215546Sopenharmony_ci
951bf215546Sopenharmony_ci   struct intel_field_iterator iter;
952bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
953bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
954bf215546Sopenharmony_ci      if (str_ends_with(iter.name, "Pointer") || !strncmp(iter.name, "Pointer", 7)) {
955bf215546Sopenharmony_ci         state_offset = iter.raw_value;
956bf215546Sopenharmony_ci         break;
957bf215546Sopenharmony_ci      }
958bf215546Sopenharmony_ci   }
959bf215546Sopenharmony_ci   decode_dynamic_state(ctx, struct_type, state_offset, count);
960bf215546Sopenharmony_ci}
961bf215546Sopenharmony_ci
962bf215546Sopenharmony_cistatic void
963bf215546Sopenharmony_cidecode_3dstate_viewport_state_pointers(struct intel_batch_decode_ctx *ctx,
964bf215546Sopenharmony_ci                                       const uint32_t *p)
965bf215546Sopenharmony_ci{
966bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
967bf215546Sopenharmony_ci   uint32_t state_offset = 0;
968bf215546Sopenharmony_ci   bool clip = false, sf = false, cc = false;
969bf215546Sopenharmony_ci   struct intel_field_iterator iter;
970bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
971bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
972bf215546Sopenharmony_ci      if (!strcmp(iter.name, "CLIP Viewport State Change"))
973bf215546Sopenharmony_ci         clip = iter.raw_value;
974bf215546Sopenharmony_ci      if (!strcmp(iter.name, "SF Viewport State Change"))
975bf215546Sopenharmony_ci         sf = iter.raw_value;
976bf215546Sopenharmony_ci      if (!strcmp(iter.name, "CC Viewport State Change"))
977bf215546Sopenharmony_ci         cc = iter.raw_value;
978bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Pointer to CLIP_VIEWPORT") && clip) {
979bf215546Sopenharmony_ci         state_offset = iter.raw_value;
980bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "CLIP_VIEWPORT", state_offset, 1);
981bf215546Sopenharmony_ci      }
982bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Pointer to SF_VIEWPORT") && sf) {
983bf215546Sopenharmony_ci         state_offset = iter.raw_value;
984bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "SF_VIEWPORT", state_offset, 1);
985bf215546Sopenharmony_ci      }
986bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Pointer to CC_VIEWPORT") && cc) {
987bf215546Sopenharmony_ci         state_offset = iter.raw_value;
988bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "CC_VIEWPORT", state_offset, 1);
989bf215546Sopenharmony_ci      }
990bf215546Sopenharmony_ci   }
991bf215546Sopenharmony_ci}
992bf215546Sopenharmony_ci
993bf215546Sopenharmony_cistatic void
994bf215546Sopenharmony_cidecode_3dstate_viewport_state_pointers_cc(struct intel_batch_decode_ctx *ctx,
995bf215546Sopenharmony_ci                                          const uint32_t *p)
996bf215546Sopenharmony_ci{
997bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "CC_VIEWPORT", p, 4);
998bf215546Sopenharmony_ci}
999bf215546Sopenharmony_ci
1000bf215546Sopenharmony_cistatic void
1001bf215546Sopenharmony_cidecode_3dstate_viewport_state_pointers_sf_clip(struct intel_batch_decode_ctx *ctx,
1002bf215546Sopenharmony_ci                                               const uint32_t *p)
1003bf215546Sopenharmony_ci{
1004bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "SF_CLIP_VIEWPORT", p, 4);
1005bf215546Sopenharmony_ci}
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_cistatic void
1008bf215546Sopenharmony_cidecode_3dstate_blend_state_pointers(struct intel_batch_decode_ctx *ctx,
1009bf215546Sopenharmony_ci                                    const uint32_t *p)
1010bf215546Sopenharmony_ci{
1011bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "BLEND_STATE", p, 1);
1012bf215546Sopenharmony_ci}
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_cistatic void
1015bf215546Sopenharmony_cidecode_3dstate_cc_state_pointers(struct intel_batch_decode_ctx *ctx,
1016bf215546Sopenharmony_ci                                 const uint32_t *p)
1017bf215546Sopenharmony_ci{
1018bf215546Sopenharmony_ci   if (ctx->devinfo.ver != 6) {
1019bf215546Sopenharmony_ci      decode_dynamic_state_pointers(ctx, "COLOR_CALC_STATE", p, 1);
1020bf215546Sopenharmony_ci      return;
1021bf215546Sopenharmony_ci   }
1022bf215546Sopenharmony_ci
1023bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_ci   uint32_t state_offset = 0;
1026bf215546Sopenharmony_ci   bool blend_change = false, ds_change = false, cc_change = false;
1027bf215546Sopenharmony_ci   struct intel_field_iterator iter;
1028bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, inst, p, 0, false);
1029bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
1030bf215546Sopenharmony_ci      if (!strcmp(iter.name, "BLEND_STATE Change"))
1031bf215546Sopenharmony_ci         blend_change = iter.raw_value;
1032bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "DEPTH_STENCIL_STATE Change"))
1033bf215546Sopenharmony_ci         ds_change = iter.raw_value;
1034bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Color Calc State Pointer Valid"))
1035bf215546Sopenharmony_ci         cc_change = iter.raw_value;
1036bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Pointer to DEPTH_STENCIL_STATE") && ds_change) {
1037bf215546Sopenharmony_ci         state_offset = iter.raw_value;
1038bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "DEPTH_STENCIL_STATE", state_offset, 1);
1039bf215546Sopenharmony_ci      }
1040bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Pointer to BLEND_STATE") && blend_change) {
1041bf215546Sopenharmony_ci         state_offset = iter.raw_value;
1042bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "BLEND_STATE", state_offset, 1);
1043bf215546Sopenharmony_ci      }
1044bf215546Sopenharmony_ci      else if (!strcmp(iter.name, "Color Calc State Pointer") && cc_change) {
1045bf215546Sopenharmony_ci         state_offset = iter.raw_value;
1046bf215546Sopenharmony_ci         decode_dynamic_state(ctx, "COLOR_CALC_STATE", state_offset, 1);
1047bf215546Sopenharmony_ci      }
1048bf215546Sopenharmony_ci   }
1049bf215546Sopenharmony_ci}
1050bf215546Sopenharmony_ci
1051bf215546Sopenharmony_cistatic void
1052bf215546Sopenharmony_cidecode_3dstate_ds_state_pointers(struct intel_batch_decode_ctx *ctx,
1053bf215546Sopenharmony_ci                                 const uint32_t *p)
1054bf215546Sopenharmony_ci{
1055bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "DEPTH_STENCIL_STATE", p, 1);
1056bf215546Sopenharmony_ci}
1057bf215546Sopenharmony_ci
1058bf215546Sopenharmony_cistatic void
1059bf215546Sopenharmony_cidecode_3dstate_scissor_state_pointers(struct intel_batch_decode_ctx *ctx,
1060bf215546Sopenharmony_ci                                      const uint32_t *p)
1061bf215546Sopenharmony_ci{
1062bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "SCISSOR_RECT", p, 1);
1063bf215546Sopenharmony_ci}
1064bf215546Sopenharmony_ci
1065bf215546Sopenharmony_cistatic void
1066bf215546Sopenharmony_cidecode_3dstate_slice_table_state_pointers(struct intel_batch_decode_ctx *ctx,
1067bf215546Sopenharmony_ci                                          const uint32_t *p)
1068bf215546Sopenharmony_ci{
1069bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "SLICE_HASH_TABLE", p, 1);
1070bf215546Sopenharmony_ci}
1071bf215546Sopenharmony_ci
1072bf215546Sopenharmony_cistatic void
1073bf215546Sopenharmony_cihandle_gt_mode(struct intel_batch_decode_ctx *ctx,
1074bf215546Sopenharmony_ci               uint32_t reg_addr, uint32_t val)
1075bf215546Sopenharmony_ci{
1076bf215546Sopenharmony_ci   struct intel_group *reg = intel_spec_find_register(ctx->spec, reg_addr);
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci   assert(intel_group_get_length(reg, &val) == 1);
1079bf215546Sopenharmony_ci
1080bf215546Sopenharmony_ci   struct intel_field_iterator iter;
1081bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, reg, &val, 0, false);
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ci   uint32_t bt_alignment;
1084bf215546Sopenharmony_ci   bool bt_alignment_mask = 0;
1085bf215546Sopenharmony_ci
1086bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
1087bf215546Sopenharmony_ci      if (strcmp(iter.name, "Binding Table Alignment") == 0) {
1088bf215546Sopenharmony_ci         bt_alignment = iter.raw_value;
1089bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Binding Table Alignment Mask") == 0) {
1090bf215546Sopenharmony_ci         bt_alignment_mask = iter.raw_value;
1091bf215546Sopenharmony_ci      }
1092bf215546Sopenharmony_ci   }
1093bf215546Sopenharmony_ci
1094bf215546Sopenharmony_ci   if (bt_alignment_mask)
1095bf215546Sopenharmony_ci      ctx->use_256B_binding_tables = bt_alignment;
1096bf215546Sopenharmony_ci}
1097bf215546Sopenharmony_ci
1098bf215546Sopenharmony_cistruct reg_handler {
1099bf215546Sopenharmony_ci   const char *name;
1100bf215546Sopenharmony_ci   void (*handler)(struct intel_batch_decode_ctx *ctx,
1101bf215546Sopenharmony_ci                   uint32_t reg_addr, uint32_t val);
1102bf215546Sopenharmony_ci} reg_handlers[] = {
1103bf215546Sopenharmony_ci   { "GT_MODE", handle_gt_mode }
1104bf215546Sopenharmony_ci};
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_cistatic void
1107bf215546Sopenharmony_cidecode_load_register_imm(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
1108bf215546Sopenharmony_ci{
1109bf215546Sopenharmony_ci   struct intel_group *inst = intel_ctx_find_instruction(ctx, p);
1110bf215546Sopenharmony_ci   const unsigned length = intel_group_get_length(inst, p);
1111bf215546Sopenharmony_ci   assert(length & 1);
1112bf215546Sopenharmony_ci   const unsigned nr_regs = (length - 1) / 2;
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci   for (unsigned i = 0; i < nr_regs; i++) {
1115bf215546Sopenharmony_ci      struct intel_group *reg = intel_spec_find_register(ctx->spec, p[i * 2 + 1]);
1116bf215546Sopenharmony_ci      if (reg != NULL) {
1117bf215546Sopenharmony_ci         fprintf(ctx->fp, "register %s (0x%x): 0x%x\n",
1118bf215546Sopenharmony_ci                 reg->name, reg->register_offset, p[2]);
1119bf215546Sopenharmony_ci         ctx_print_group(ctx, reg, reg->register_offset, &p[2]);
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci         for (unsigned i = 0; i < ARRAY_SIZE(reg_handlers); i++) {
1122bf215546Sopenharmony_ci            if (strcmp(reg->name, reg_handlers[i].name) == 0)
1123bf215546Sopenharmony_ci               reg_handlers[i].handler(ctx, p[1], p[2]);
1124bf215546Sopenharmony_ci         }
1125bf215546Sopenharmony_ci      }
1126bf215546Sopenharmony_ci   }
1127bf215546Sopenharmony_ci}
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_cistatic void
1130bf215546Sopenharmony_cidecode_vs_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1131bf215546Sopenharmony_ci{
1132bf215546Sopenharmony_ci   struct intel_group *strct =
1133bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "VS_STATE");
1134bf215546Sopenharmony_ci   if (strct == NULL) {
1135bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find VS_STATE info\n");
1136bf215546Sopenharmony_ci      return;
1137bf215546Sopenharmony_ci   }
1138bf215546Sopenharmony_ci
1139bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1140bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1141bf215546Sopenharmony_ci
1142bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1143bf215546Sopenharmony_ci      fprintf(ctx->fp, " vs state unavailable\n");
1144bf215546Sopenharmony_ci      return;
1145bf215546Sopenharmony_ci   }
1146bf215546Sopenharmony_ci
1147bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   uint64_t ksp = 0;
1150bf215546Sopenharmony_ci   bool is_enabled = true;
1151bf215546Sopenharmony_ci   struct intel_field_iterator iter;
1152bf215546Sopenharmony_ci   intel_field_iterator_init(&iter, strct, bind_bo.map, 0, false);
1153bf215546Sopenharmony_ci   while (intel_field_iterator_next(&iter)) {
1154bf215546Sopenharmony_ci      if (strcmp(iter.name, "Kernel Start Pointer") == 0) {
1155bf215546Sopenharmony_ci         ksp = iter.raw_value;
1156bf215546Sopenharmony_ci      } else if (strcmp(iter.name, "Enable") == 0) {
1157bf215546Sopenharmony_ci	is_enabled = iter.raw_value;
1158bf215546Sopenharmony_ci      }
1159bf215546Sopenharmony_ci   }
1160bf215546Sopenharmony_ci   if (is_enabled) {
1161bf215546Sopenharmony_ci      ctx_disassemble_program(ctx, ksp, "vertex shader");
1162bf215546Sopenharmony_ci      fprintf(ctx->fp, "\n");
1163bf215546Sopenharmony_ci   }
1164bf215546Sopenharmony_ci}
1165bf215546Sopenharmony_ci
1166bf215546Sopenharmony_cistatic void
1167bf215546Sopenharmony_cidecode_gs_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1168bf215546Sopenharmony_ci{
1169bf215546Sopenharmony_ci   struct intel_group *strct =
1170bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "GS_STATE");
1171bf215546Sopenharmony_ci   if (strct == NULL) {
1172bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find GS_STATE info\n");
1173bf215546Sopenharmony_ci      return;
1174bf215546Sopenharmony_ci   }
1175bf215546Sopenharmony_ci
1176bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1177bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1180bf215546Sopenharmony_ci      fprintf(ctx->fp, " gs state unavailable\n");
1181bf215546Sopenharmony_ci      return;
1182bf215546Sopenharmony_ci   }
1183bf215546Sopenharmony_ci
1184bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1185bf215546Sopenharmony_ci}
1186bf215546Sopenharmony_ci
1187bf215546Sopenharmony_cistatic void
1188bf215546Sopenharmony_cidecode_clip_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1189bf215546Sopenharmony_ci{
1190bf215546Sopenharmony_ci   struct intel_group *strct =
1191bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "CLIP_STATE");
1192bf215546Sopenharmony_ci   if (strct == NULL) {
1193bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find CLIP_STATE info\n");
1194bf215546Sopenharmony_ci      return;
1195bf215546Sopenharmony_ci   }
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1198bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1201bf215546Sopenharmony_ci      fprintf(ctx->fp, " clip state unavailable\n");
1202bf215546Sopenharmony_ci      return;
1203bf215546Sopenharmony_ci   }
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_ci   struct intel_group *vp_strct =
1208bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "CLIP_VIEWPORT");
1209bf215546Sopenharmony_ci   if (vp_strct == NULL) {
1210bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find CLIP_VIEWPORT info\n");
1211bf215546Sopenharmony_ci      return;
1212bf215546Sopenharmony_ci   }
1213bf215546Sopenharmony_ci   uint32_t clip_vp_offset = ((uint32_t *)bind_bo.map)[6] & ~0x3;
1214bf215546Sopenharmony_ci   struct intel_batch_decode_bo vp_bo =
1215bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, clip_vp_offset);
1216bf215546Sopenharmony_ci   if (vp_bo.map == NULL) {
1217bf215546Sopenharmony_ci      fprintf(ctx->fp, " clip vp state unavailable\n");
1218bf215546Sopenharmony_ci      return;
1219bf215546Sopenharmony_ci   }
1220bf215546Sopenharmony_ci   ctx_print_group(ctx, vp_strct, clip_vp_offset, vp_bo.map);
1221bf215546Sopenharmony_ci}
1222bf215546Sopenharmony_ci
1223bf215546Sopenharmony_cistatic void
1224bf215546Sopenharmony_cidecode_sf_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1225bf215546Sopenharmony_ci{
1226bf215546Sopenharmony_ci   struct intel_group *strct =
1227bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "SF_STATE");
1228bf215546Sopenharmony_ci   if (strct == NULL) {
1229bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find SF_STATE info\n");
1230bf215546Sopenharmony_ci      return;
1231bf215546Sopenharmony_ci   }
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1234bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1235bf215546Sopenharmony_ci
1236bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1237bf215546Sopenharmony_ci      fprintf(ctx->fp, " sf state unavailable\n");
1238bf215546Sopenharmony_ci      return;
1239bf215546Sopenharmony_ci   }
1240bf215546Sopenharmony_ci
1241bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_ci   struct intel_group *vp_strct =
1244bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "SF_VIEWPORT");
1245bf215546Sopenharmony_ci   if (vp_strct == NULL) {
1246bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find SF_VIEWPORT info\n");
1247bf215546Sopenharmony_ci      return;
1248bf215546Sopenharmony_ci   }
1249bf215546Sopenharmony_ci
1250bf215546Sopenharmony_ci   uint32_t sf_vp_offset = ((uint32_t *)bind_bo.map)[5] & ~0x3;
1251bf215546Sopenharmony_ci   struct intel_batch_decode_bo vp_bo =
1252bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, sf_vp_offset);
1253bf215546Sopenharmony_ci   if (vp_bo.map == NULL) {
1254bf215546Sopenharmony_ci      fprintf(ctx->fp, " sf vp state unavailable\n");
1255bf215546Sopenharmony_ci      return;
1256bf215546Sopenharmony_ci   }
1257bf215546Sopenharmony_ci   ctx_print_group(ctx, vp_strct, sf_vp_offset, vp_bo.map);
1258bf215546Sopenharmony_ci}
1259bf215546Sopenharmony_ci
1260bf215546Sopenharmony_cistatic void
1261bf215546Sopenharmony_cidecode_wm_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1262bf215546Sopenharmony_ci{
1263bf215546Sopenharmony_ci   struct intel_group *strct =
1264bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "WM_STATE");
1265bf215546Sopenharmony_ci   if (strct == NULL) {
1266bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find WM_STATE info\n");
1267bf215546Sopenharmony_ci      return;
1268bf215546Sopenharmony_ci   }
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1271bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1272bf215546Sopenharmony_ci
1273bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1274bf215546Sopenharmony_ci      fprintf(ctx->fp, " wm state unavailable\n");
1275bf215546Sopenharmony_ci      return;
1276bf215546Sopenharmony_ci   }
1277bf215546Sopenharmony_ci
1278bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1279bf215546Sopenharmony_ci
1280bf215546Sopenharmony_ci   decode_ps_kern(ctx, strct, bind_bo.map);
1281bf215546Sopenharmony_ci}
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_cistatic void
1284bf215546Sopenharmony_cidecode_cc_state(struct intel_batch_decode_ctx *ctx, uint32_t offset)
1285bf215546Sopenharmony_ci{
1286bf215546Sopenharmony_ci   struct intel_group *strct =
1287bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "COLOR_CALC_STATE");
1288bf215546Sopenharmony_ci   if (strct == NULL) {
1289bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find COLOR_CALC_STATE info\n");
1290bf215546Sopenharmony_ci      return;
1291bf215546Sopenharmony_ci   }
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci   struct intel_batch_decode_bo bind_bo =
1294bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, offset);
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_ci   if (bind_bo.map == NULL) {
1297bf215546Sopenharmony_ci      fprintf(ctx->fp, " cc state unavailable\n");
1298bf215546Sopenharmony_ci      return;
1299bf215546Sopenharmony_ci   }
1300bf215546Sopenharmony_ci
1301bf215546Sopenharmony_ci   ctx_print_group(ctx, strct, offset, bind_bo.map);
1302bf215546Sopenharmony_ci
1303bf215546Sopenharmony_ci   struct intel_group *vp_strct =
1304bf215546Sopenharmony_ci      intel_spec_find_struct(ctx->spec, "CC_VIEWPORT");
1305bf215546Sopenharmony_ci   if (vp_strct == NULL) {
1306bf215546Sopenharmony_ci      fprintf(ctx->fp, "did not find CC_VIEWPORT info\n");
1307bf215546Sopenharmony_ci      return;
1308bf215546Sopenharmony_ci   }
1309bf215546Sopenharmony_ci   uint32_t cc_vp_offset = ((uint32_t *)bind_bo.map)[4] & ~0x3;
1310bf215546Sopenharmony_ci   struct intel_batch_decode_bo vp_bo =
1311bf215546Sopenharmony_ci      ctx_get_bo(ctx, true, cc_vp_offset);
1312bf215546Sopenharmony_ci   if (vp_bo.map == NULL) {
1313bf215546Sopenharmony_ci      fprintf(ctx->fp, " cc vp state unavailable\n");
1314bf215546Sopenharmony_ci      return;
1315bf215546Sopenharmony_ci   }
1316bf215546Sopenharmony_ci   ctx_print_group(ctx, vp_strct, cc_vp_offset, vp_bo.map);
1317bf215546Sopenharmony_ci}
1318bf215546Sopenharmony_cistatic void
1319bf215546Sopenharmony_cidecode_pipelined_pointers(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
1320bf215546Sopenharmony_ci{
1321bf215546Sopenharmony_ci   fprintf(ctx->fp, "VS State Table:\n");
1322bf215546Sopenharmony_ci   decode_vs_state(ctx, p[1]);
1323bf215546Sopenharmony_ci   if (p[2] & 1) {
1324bf215546Sopenharmony_ci      fprintf(ctx->fp, "GS State Table:\n");
1325bf215546Sopenharmony_ci      decode_gs_state(ctx, p[2] & ~1);
1326bf215546Sopenharmony_ci   }
1327bf215546Sopenharmony_ci   fprintf(ctx->fp, "Clip State Table:\n");
1328bf215546Sopenharmony_ci   decode_clip_state(ctx, p[3] & ~1);
1329bf215546Sopenharmony_ci   fprintf(ctx->fp, "SF State Table:\n");
1330bf215546Sopenharmony_ci   decode_sf_state(ctx, p[4]);
1331bf215546Sopenharmony_ci   fprintf(ctx->fp, "WM State Table:\n");
1332bf215546Sopenharmony_ci   decode_wm_state(ctx, p[5]);
1333bf215546Sopenharmony_ci   fprintf(ctx->fp, "CC State Table:\n");
1334bf215546Sopenharmony_ci   decode_cc_state(ctx, p[6]);
1335bf215546Sopenharmony_ci}
1336bf215546Sopenharmony_ci
1337bf215546Sopenharmony_cistatic void
1338bf215546Sopenharmony_cidecode_cps_pointers(struct intel_batch_decode_ctx *ctx, const uint32_t *p)
1339bf215546Sopenharmony_ci{
1340bf215546Sopenharmony_ci   decode_dynamic_state_pointers(ctx, "CPS_STATE", p, 1);
1341bf215546Sopenharmony_ci}
1342bf215546Sopenharmony_ci
1343bf215546Sopenharmony_cistruct custom_decoder {
1344bf215546Sopenharmony_ci   const char *cmd_name;
1345bf215546Sopenharmony_ci   void (*decode)(struct intel_batch_decode_ctx *ctx, const uint32_t *p);
1346bf215546Sopenharmony_ci} custom_decoders[] = {
1347bf215546Sopenharmony_ci   { "STATE_BASE_ADDRESS", handle_state_base_address },
1348bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POOL_ALLOC", handle_binding_table_pool_alloc },
1349bf215546Sopenharmony_ci   { "MEDIA_INTERFACE_DESCRIPTOR_LOAD", handle_media_interface_descriptor_load },
1350bf215546Sopenharmony_ci   { "COMPUTE_WALKER", handle_compute_walker },
1351bf215546Sopenharmony_ci   { "3DSTATE_VERTEX_BUFFERS", handle_3dstate_vertex_buffers },
1352bf215546Sopenharmony_ci   { "3DSTATE_INDEX_BUFFER", handle_3dstate_index_buffer },
1353bf215546Sopenharmony_ci   { "3DSTATE_VS", decode_single_ksp },
1354bf215546Sopenharmony_ci   { "3DSTATE_GS", decode_single_ksp },
1355bf215546Sopenharmony_ci   { "3DSTATE_DS", decode_single_ksp },
1356bf215546Sopenharmony_ci   { "3DSTATE_HS", decode_single_ksp },
1357bf215546Sopenharmony_ci   { "3DSTATE_PS", decode_ps_kernels },
1358bf215546Sopenharmony_ci   { "3DSTATE_WM", decode_ps_kernels },
1359bf215546Sopenharmony_ci   { "3DSTATE_MESH_SHADER", decode_mesh_task_ksp },
1360bf215546Sopenharmony_ci   { "3DSTATE_TASK_SHADER", decode_mesh_task_ksp },
1361bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_VS", decode_3dstate_constant },
1362bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_GS", decode_3dstate_constant },
1363bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_PS", decode_3dstate_constant },
1364bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_HS", decode_3dstate_constant },
1365bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_DS", decode_3dstate_constant },
1366bf215546Sopenharmony_ci   { "3DSTATE_CONSTANT_ALL", decode_3dstate_constant_all },
1367bf215546Sopenharmony_ci
1368bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS", decode_gfx4_3dstate_binding_table_pointers },
1369bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS_VS", decode_3dstate_binding_table_pointers },
1370bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS_HS", decode_3dstate_binding_table_pointers },
1371bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS_DS", decode_3dstate_binding_table_pointers },
1372bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS_GS", decode_3dstate_binding_table_pointers },
1373bf215546Sopenharmony_ci   { "3DSTATE_BINDING_TABLE_POINTERS_PS", decode_3dstate_binding_table_pointers },
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS_VS", decode_3dstate_sampler_state_pointers },
1376bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS_HS", decode_3dstate_sampler_state_pointers },
1377bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS_DS", decode_3dstate_sampler_state_pointers },
1378bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS_GS", decode_3dstate_sampler_state_pointers },
1379bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS_PS", decode_3dstate_sampler_state_pointers },
1380bf215546Sopenharmony_ci   { "3DSTATE_SAMPLER_STATE_POINTERS", decode_3dstate_sampler_state_pointers_gfx6 },
1381bf215546Sopenharmony_ci
1382bf215546Sopenharmony_ci   { "3DSTATE_VIEWPORT_STATE_POINTERS", decode_3dstate_viewport_state_pointers },
1383bf215546Sopenharmony_ci   { "3DSTATE_VIEWPORT_STATE_POINTERS_CC", decode_3dstate_viewport_state_pointers_cc },
1384bf215546Sopenharmony_ci   { "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", decode_3dstate_viewport_state_pointers_sf_clip },
1385bf215546Sopenharmony_ci   { "3DSTATE_BLEND_STATE_POINTERS", decode_3dstate_blend_state_pointers },
1386bf215546Sopenharmony_ci   { "3DSTATE_CC_STATE_POINTERS", decode_3dstate_cc_state_pointers },
1387bf215546Sopenharmony_ci   { "3DSTATE_DEPTH_STENCIL_STATE_POINTERS", decode_3dstate_ds_state_pointers },
1388bf215546Sopenharmony_ci   { "3DSTATE_SCISSOR_STATE_POINTERS", decode_3dstate_scissor_state_pointers },
1389bf215546Sopenharmony_ci   { "3DSTATE_SLICE_TABLE_STATE_POINTERS", decode_3dstate_slice_table_state_pointers },
1390bf215546Sopenharmony_ci   { "MI_LOAD_REGISTER_IMM", decode_load_register_imm },
1391bf215546Sopenharmony_ci   { "3DSTATE_PIPELINED_POINTERS", decode_pipelined_pointers },
1392bf215546Sopenharmony_ci   { "3DSTATE_CPS_POINTERS", decode_cps_pointers },
1393bf215546Sopenharmony_ci   { "CONSTANT_BUFFER", decode_gfx4_constant_buffer },
1394bf215546Sopenharmony_ci};
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_civoid
1397bf215546Sopenharmony_ciintel_print_batch(struct intel_batch_decode_ctx *ctx,
1398bf215546Sopenharmony_ci                  const uint32_t *batch, uint32_t batch_size,
1399bf215546Sopenharmony_ci                  uint64_t batch_addr, bool from_ring)
1400bf215546Sopenharmony_ci{
1401bf215546Sopenharmony_ci   const uint32_t *p, *end = batch + batch_size / sizeof(uint32_t);
1402bf215546Sopenharmony_ci   int length;
1403bf215546Sopenharmony_ci   struct intel_group *inst;
1404bf215546Sopenharmony_ci   const char *reset_color = ctx->flags & INTEL_BATCH_DECODE_IN_COLOR ? NORMAL : "";
1405bf215546Sopenharmony_ci
1406bf215546Sopenharmony_ci   if (ctx->n_batch_buffer_start >= 100) {
1407bf215546Sopenharmony_ci      fprintf(ctx->fp, "%s0x%08"PRIx64": Max batch buffer jumps exceeded%s\n",
1408bf215546Sopenharmony_ci              (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",
1409bf215546Sopenharmony_ci              (ctx->flags & INTEL_BATCH_DECODE_OFFSETS) ? batch_addr : 0,
1410bf215546Sopenharmony_ci              reset_color);
1411bf215546Sopenharmony_ci      return;
1412bf215546Sopenharmony_ci   }
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci   ctx->n_batch_buffer_start++;
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_ci   for (p = batch; p < end; p += length) {
1417bf215546Sopenharmony_ci      inst = intel_ctx_find_instruction(ctx, p);
1418bf215546Sopenharmony_ci      length = intel_group_get_length(inst, p);
1419bf215546Sopenharmony_ci      assert(inst == NULL || length > 0);
1420bf215546Sopenharmony_ci      length = MAX2(1, length);
1421bf215546Sopenharmony_ci
1422bf215546Sopenharmony_ci      uint64_t offset;
1423bf215546Sopenharmony_ci      if (ctx->flags & INTEL_BATCH_DECODE_OFFSETS)
1424bf215546Sopenharmony_ci         offset = batch_addr + ((char *)p - (char *)batch);
1425bf215546Sopenharmony_ci      else
1426bf215546Sopenharmony_ci         offset = 0;
1427bf215546Sopenharmony_ci
1428bf215546Sopenharmony_ci      if (inst == NULL) {
1429bf215546Sopenharmony_ci         fprintf(ctx->fp, "%s0x%08"PRIx64": unknown instruction %08x%s\n",
1430bf215546Sopenharmony_ci                 (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",
1431bf215546Sopenharmony_ci                 offset, p[0], reset_color);
1432bf215546Sopenharmony_ci
1433bf215546Sopenharmony_ci         for (int i=1; i < length; i++) {
1434bf215546Sopenharmony_ci            fprintf(ctx->fp, "%s0x%08"PRIx64": -- %08x%s\n",
1435bf215546Sopenharmony_ci                 (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) ? RED_COLOR : "",
1436bf215546Sopenharmony_ci                 offset + i * 4, p[i], reset_color);
1437bf215546Sopenharmony_ci         }
1438bf215546Sopenharmony_ci
1439bf215546Sopenharmony_ci         continue;
1440bf215546Sopenharmony_ci      }
1441bf215546Sopenharmony_ci
1442bf215546Sopenharmony_ci      const char *color;
1443bf215546Sopenharmony_ci      const char *inst_name = intel_group_get_name(inst);
1444bf215546Sopenharmony_ci      if (ctx->flags & INTEL_BATCH_DECODE_IN_COLOR) {
1445bf215546Sopenharmony_ci         reset_color = NORMAL;
1446bf215546Sopenharmony_ci         if (ctx->flags & INTEL_BATCH_DECODE_FULL) {
1447bf215546Sopenharmony_ci            if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0 ||
1448bf215546Sopenharmony_ci                strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0)
1449bf215546Sopenharmony_ci               color = GREEN_HEADER;
1450bf215546Sopenharmony_ci            else
1451bf215546Sopenharmony_ci               color = BLUE_HEADER;
1452bf215546Sopenharmony_ci         } else {
1453bf215546Sopenharmony_ci            color = NORMAL;
1454bf215546Sopenharmony_ci         }
1455bf215546Sopenharmony_ci      } else {
1456bf215546Sopenharmony_ci         color = "";
1457bf215546Sopenharmony_ci         reset_color = "";
1458bf215546Sopenharmony_ci      }
1459bf215546Sopenharmony_ci
1460bf215546Sopenharmony_ci      fprintf(ctx->fp, "%s0x%08"PRIx64"%s:  0x%08x:  %-80s%s\n", color, offset,
1461bf215546Sopenharmony_ci              ctx->acthd && offset == ctx->acthd ? " (ACTHD)" : "", p[0],
1462bf215546Sopenharmony_ci              inst_name, reset_color);
1463bf215546Sopenharmony_ci
1464bf215546Sopenharmony_ci      if (ctx->flags & INTEL_BATCH_DECODE_FULL) {
1465bf215546Sopenharmony_ci         ctx_print_group(ctx, inst, offset, p);
1466bf215546Sopenharmony_ci
1467bf215546Sopenharmony_ci         for (int i = 0; i < ARRAY_SIZE(custom_decoders); i++) {
1468bf215546Sopenharmony_ci            if (strcmp(inst_name, custom_decoders[i].cmd_name) == 0) {
1469bf215546Sopenharmony_ci               custom_decoders[i].decode(ctx, p);
1470bf215546Sopenharmony_ci               break;
1471bf215546Sopenharmony_ci            }
1472bf215546Sopenharmony_ci         }
1473bf215546Sopenharmony_ci      }
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci      if (strcmp(inst_name, "MI_BATCH_BUFFER_START") == 0) {
1476bf215546Sopenharmony_ci         uint64_t next_batch_addr = 0;
1477bf215546Sopenharmony_ci         bool ppgtt = false;
1478bf215546Sopenharmony_ci         bool second_level = false;
1479bf215546Sopenharmony_ci         bool predicate = false;
1480bf215546Sopenharmony_ci         struct intel_field_iterator iter;
1481bf215546Sopenharmony_ci         intel_field_iterator_init(&iter, inst, p, 0, false);
1482bf215546Sopenharmony_ci         while (intel_field_iterator_next(&iter)) {
1483bf215546Sopenharmony_ci            if (strcmp(iter.name, "Batch Buffer Start Address") == 0) {
1484bf215546Sopenharmony_ci               next_batch_addr = iter.raw_value;
1485bf215546Sopenharmony_ci            } else if (strcmp(iter.name, "Second Level Batch Buffer") == 0) {
1486bf215546Sopenharmony_ci               second_level = iter.raw_value;
1487bf215546Sopenharmony_ci            } else if (strcmp(iter.name, "Address Space Indicator") == 0) {
1488bf215546Sopenharmony_ci               ppgtt = iter.raw_value;
1489bf215546Sopenharmony_ci            } else if (strcmp(iter.name, "Predication Enable") == 0) {
1490bf215546Sopenharmony_ci               predicate = iter.raw_value;
1491bf215546Sopenharmony_ci            }
1492bf215546Sopenharmony_ci         }
1493bf215546Sopenharmony_ci
1494bf215546Sopenharmony_ci         if (!predicate) {
1495bf215546Sopenharmony_ci            struct intel_batch_decode_bo next_batch = ctx_get_bo(ctx, ppgtt, next_batch_addr);
1496bf215546Sopenharmony_ci
1497bf215546Sopenharmony_ci            if (next_batch.map == NULL) {
1498bf215546Sopenharmony_ci               fprintf(ctx->fp, "Secondary batch at 0x%08"PRIx64" unavailable\n",
1499bf215546Sopenharmony_ci                       next_batch_addr);
1500bf215546Sopenharmony_ci            } else {
1501bf215546Sopenharmony_ci               intel_print_batch(ctx, next_batch.map, next_batch.size,
1502bf215546Sopenharmony_ci                                 next_batch.addr, false);
1503bf215546Sopenharmony_ci            }
1504bf215546Sopenharmony_ci            if (second_level) {
1505bf215546Sopenharmony_ci               /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" set acts
1506bf215546Sopenharmony_ci                * like a subroutine call.  Commands that come afterwards get
1507bf215546Sopenharmony_ci                * processed once the 2nd level batch buffer returns with
1508bf215546Sopenharmony_ci                * MI_BATCH_BUFFER_END.
1509bf215546Sopenharmony_ci                */
1510bf215546Sopenharmony_ci               continue;
1511bf215546Sopenharmony_ci            } else if (!from_ring) {
1512bf215546Sopenharmony_ci               /* MI_BATCH_BUFFER_START with "2nd Level Batch Buffer" unset acts
1513bf215546Sopenharmony_ci                * like a goto.  Nothing after it will ever get processed.  In
1514bf215546Sopenharmony_ci                * order to prevent the recursion from growing, we just reset the
1515bf215546Sopenharmony_ci                * loop and continue;
1516bf215546Sopenharmony_ci                */
1517bf215546Sopenharmony_ci               break;
1518bf215546Sopenharmony_ci            }
1519bf215546Sopenharmony_ci         }
1520bf215546Sopenharmony_ci      } else if (strcmp(inst_name, "MI_BATCH_BUFFER_END") == 0) {
1521bf215546Sopenharmony_ci         break;
1522bf215546Sopenharmony_ci      }
1523bf215546Sopenharmony_ci   }
1524bf215546Sopenharmony_ci
1525bf215546Sopenharmony_ci   ctx->n_batch_buffer_start--;
1526bf215546Sopenharmony_ci}
1527