1/*
2 * Copyright © 2008 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <string.h>
25#include <stdarg.h>
26
27#include "brw_eu_defines.h"
28#include "brw_inst.h"
29#include "brw_shader.h"
30#include "brw_reg.h"
31#include "brw_inst.h"
32#include "brw_eu.h"
33#include "util/half_float.h"
34
35bool
36brw_has_jip(const struct intel_device_info *devinfo, enum opcode opcode)
37{
38   if (devinfo->ver < 6)
39      return false;
40
41   return opcode == BRW_OPCODE_IF ||
42          opcode == BRW_OPCODE_ELSE ||
43          opcode == BRW_OPCODE_ENDIF ||
44          opcode == BRW_OPCODE_WHILE ||
45          opcode == BRW_OPCODE_BREAK ||
46          opcode == BRW_OPCODE_CONTINUE ||
47          opcode == BRW_OPCODE_HALT;
48}
49
50bool
51brw_has_uip(const struct intel_device_info *devinfo, enum opcode opcode)
52{
53   if (devinfo->ver < 6)
54      return false;
55
56   return (devinfo->ver >= 7 && opcode == BRW_OPCODE_IF) ||
57          (devinfo->ver >= 8 && opcode == BRW_OPCODE_ELSE) ||
58          opcode == BRW_OPCODE_BREAK ||
59          opcode == BRW_OPCODE_CONTINUE ||
60          opcode == BRW_OPCODE_HALT;
61}
62
63static bool
64has_branch_ctrl(const struct intel_device_info *devinfo, enum opcode opcode)
65{
66   if (devinfo->ver < 8)
67      return false;
68
69   return opcode == BRW_OPCODE_IF ||
70          opcode == BRW_OPCODE_ELSE;
71          /* opcode == BRW_OPCODE_GOTO; */
72}
73
74static bool
75is_logic_instruction(unsigned opcode)
76{
77   return opcode == BRW_OPCODE_AND ||
78          opcode == BRW_OPCODE_NOT ||
79          opcode == BRW_OPCODE_OR ||
80          opcode == BRW_OPCODE_XOR;
81}
82
83static bool
84is_send(unsigned opcode)
85{
86   return opcode == BRW_OPCODE_SEND ||
87          opcode == BRW_OPCODE_SENDC ||
88          opcode == BRW_OPCODE_SENDS ||
89          opcode == BRW_OPCODE_SENDSC;
90}
91
92static bool
93is_split_send(UNUSED const struct intel_device_info *devinfo, unsigned opcode)
94{
95   if (devinfo->ver >= 12)
96      return is_send(opcode);
97   else
98      return opcode == BRW_OPCODE_SENDS ||
99             opcode == BRW_OPCODE_SENDSC;
100}
101
102const char *const conditional_modifier[16] = {
103   [BRW_CONDITIONAL_NONE] = "",
104   [BRW_CONDITIONAL_Z]    = ".z",
105   [BRW_CONDITIONAL_NZ]   = ".nz",
106   [BRW_CONDITIONAL_G]    = ".g",
107   [BRW_CONDITIONAL_GE]   = ".ge",
108   [BRW_CONDITIONAL_L]    = ".l",
109   [BRW_CONDITIONAL_LE]   = ".le",
110   [BRW_CONDITIONAL_R]    = ".r",
111   [BRW_CONDITIONAL_O]    = ".o",
112   [BRW_CONDITIONAL_U]    = ".u",
113};
114
115static const char *const m_negate[2] = {
116   [0] = "",
117   [1] = "-",
118};
119
120static const char *const _abs[2] = {
121   [0] = "",
122   [1] = "(abs)",
123};
124
125static const char *const m_bitnot[2] = { "", "~" };
126
127static const char *const vert_stride[16] = {
128   [0] = "0",
129   [1] = "1",
130   [2] = "2",
131   [3] = "4",
132   [4] = "8",
133   [5] = "16",
134   [6] = "32",
135   [15] = "VxH",
136};
137
138static const char *const width[8] = {
139   [0] = "1",
140   [1] = "2",
141   [2] = "4",
142   [3] = "8",
143   [4] = "16",
144};
145
146static const char *const horiz_stride[4] = {
147   [0] = "0",
148   [1] = "1",
149   [2] = "2",
150   [3] = "4"
151};
152
153static const char *const chan_sel[4] = {
154   [0] = "x",
155   [1] = "y",
156   [2] = "z",
157   [3] = "w",
158};
159
160static const char *const debug_ctrl[2] = {
161   [0] = "",
162   [1] = ".breakpoint"
163};
164
165static const char *const saturate[2] = {
166   [0] = "",
167   [1] = ".sat"
168};
169
170static const char *const cmpt_ctrl[2] = {
171   [0] = "",
172   [1] = "compacted"
173};
174
175static const char *const accwr[2] = {
176   [0] = "",
177   [1] = "AccWrEnable"
178};
179
180static const char *const branch_ctrl[2] = {
181   [0] = "",
182   [1] = "BranchCtrl"
183};
184
185static const char *const wectrl[2] = {
186   [0] = "",
187   [1] = "WE_all"
188};
189
190static const char *const exec_size[8] = {
191   [0] = "1",
192   [1] = "2",
193   [2] = "4",
194   [3] = "8",
195   [4] = "16",
196   [5] = "32"
197};
198
199static const char *const pred_inv[2] = {
200   [0] = "+",
201   [1] = "-"
202};
203
204const char *const pred_ctrl_align16[16] = {
205   [1] = "",
206   [2] = ".x",
207   [3] = ".y",
208   [4] = ".z",
209   [5] = ".w",
210   [6] = ".any4h",
211   [7] = ".all4h",
212};
213
214static const char *const pred_ctrl_align1[16] = {
215   [BRW_PREDICATE_NORMAL]        = "",
216   [BRW_PREDICATE_ALIGN1_ANYV]   = ".anyv",
217   [BRW_PREDICATE_ALIGN1_ALLV]   = ".allv",
218   [BRW_PREDICATE_ALIGN1_ANY2H]  = ".any2h",
219   [BRW_PREDICATE_ALIGN1_ALL2H]  = ".all2h",
220   [BRW_PREDICATE_ALIGN1_ANY4H]  = ".any4h",
221   [BRW_PREDICATE_ALIGN1_ALL4H]  = ".all4h",
222   [BRW_PREDICATE_ALIGN1_ANY8H]  = ".any8h",
223   [BRW_PREDICATE_ALIGN1_ALL8H]  = ".all8h",
224   [BRW_PREDICATE_ALIGN1_ANY16H] = ".any16h",
225   [BRW_PREDICATE_ALIGN1_ALL16H] = ".all16h",
226   [BRW_PREDICATE_ALIGN1_ANY32H] = ".any32h",
227   [BRW_PREDICATE_ALIGN1_ALL32H] = ".all32h",
228};
229
230static const char *const thread_ctrl[4] = {
231   [BRW_THREAD_NORMAL] = "",
232   [BRW_THREAD_ATOMIC] = "atomic",
233   [BRW_THREAD_SWITCH] = "switch",
234};
235
236static const char *const compr_ctrl[4] = {
237   [0] = "",
238   [1] = "sechalf",
239   [2] = "compr",
240   [3] = "compr4",
241};
242
243static const char *const dep_ctrl[4] = {
244   [0] = "",
245   [1] = "NoDDClr",
246   [2] = "NoDDChk",
247   [3] = "NoDDClr,NoDDChk",
248};
249
250static const char *const mask_ctrl[4] = {
251   [0] = "",
252   [1] = "nomask",
253};
254
255static const char *const access_mode[2] = {
256   [0] = "align1",
257   [1] = "align16",
258};
259
260static const char *const reg_file[4] = {
261   [0] = "A",
262   [1] = "g",
263   [2] = "m",
264   [3] = "imm",
265};
266
267static const char *const writemask[16] = {
268   [0x0] = ".",
269   [0x1] = ".x",
270   [0x2] = ".y",
271   [0x3] = ".xy",
272   [0x4] = ".z",
273   [0x5] = ".xz",
274   [0x6] = ".yz",
275   [0x7] = ".xyz",
276   [0x8] = ".w",
277   [0x9] = ".xw",
278   [0xa] = ".yw",
279   [0xb] = ".xyw",
280   [0xc] = ".zw",
281   [0xd] = ".xzw",
282   [0xe] = ".yzw",
283   [0xf] = "",
284};
285
286static const char *const end_of_thread[2] = {
287   [0] = "",
288   [1] = "EOT"
289};
290
291/* SFIDs on Gfx4-5 */
292static const char *const gfx4_sfid[16] = {
293   [BRW_SFID_NULL]            = "null",
294   [BRW_SFID_MATH]            = "math",
295   [BRW_SFID_SAMPLER]         = "sampler",
296   [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
297   [BRW_SFID_DATAPORT_READ]   = "read",
298   [BRW_SFID_DATAPORT_WRITE]  = "write",
299   [BRW_SFID_URB]             = "urb",
300   [BRW_SFID_THREAD_SPAWNER]  = "thread_spawner",
301   [BRW_SFID_VME]             = "vme",
302};
303
304static const char *const gfx6_sfid[16] = {
305   [BRW_SFID_NULL]                     = "null",
306   [BRW_SFID_MATH]                     = "math",
307   [BRW_SFID_SAMPLER]                  = "sampler",
308   [BRW_SFID_MESSAGE_GATEWAY]          = "gateway",
309   [BRW_SFID_URB]                      = "urb",
310   [BRW_SFID_THREAD_SPAWNER]           = "thread_spawner",
311   [GFX6_SFID_DATAPORT_SAMPLER_CACHE]  = "dp_sampler",
312   [GFX6_SFID_DATAPORT_RENDER_CACHE]   = "render",
313   [GFX6_SFID_DATAPORT_CONSTANT_CACHE] = "const",
314   [GFX7_SFID_DATAPORT_DATA_CACHE]     = "data",
315   [GFX7_SFID_PIXEL_INTERPOLATOR]      = "pixel interp",
316   [HSW_SFID_DATAPORT_DATA_CACHE_1]    = "dp data 1",
317   [HSW_SFID_CRE]                      = "cre",
318   [GEN_RT_SFID_RAY_TRACE_ACCELERATOR] = "rt accel",
319   [GFX12_SFID_SLM]                    = "slm",
320   [GFX12_SFID_TGM]                    = "tgm",
321   [GFX12_SFID_UGM]                    = "ugm",
322};
323
324static const char *const gfx7_gateway_subfuncid[8] = {
325   [BRW_MESSAGE_GATEWAY_SFID_OPEN_GATEWAY] = "open",
326   [BRW_MESSAGE_GATEWAY_SFID_CLOSE_GATEWAY] = "close",
327   [BRW_MESSAGE_GATEWAY_SFID_FORWARD_MSG] = "forward msg",
328   [BRW_MESSAGE_GATEWAY_SFID_GET_TIMESTAMP] = "get timestamp",
329   [BRW_MESSAGE_GATEWAY_SFID_BARRIER_MSG] = "barrier msg",
330   [BRW_MESSAGE_GATEWAY_SFID_UPDATE_GATEWAY_STATE] = "update state",
331   [BRW_MESSAGE_GATEWAY_SFID_MMIO_READ_WRITE] = "mmio read/write",
332};
333
334static const char *const gfx4_dp_read_port_msg_type[4] = {
335   [0b00] = "OWord Block Read",
336   [0b01] = "OWord Dual Block Read",
337   [0b10] = "Media Block Read",
338   [0b11] = "DWord Scattered Read",
339};
340
341static const char *const g45_dp_read_port_msg_type[8] = {
342   [0b000] = "OWord Block Read",
343   [0b010] = "OWord Dual Block Read",
344   [0b100] = "Media Block Read",
345   [0b110] = "DWord Scattered Read",
346   [0b001] = "Render Target UNORM Read",
347   [0b011] = "AVC Loop Filter Read",
348};
349
350static const char *const dp_write_port_msg_type[8] = {
351   [0b000] = "OWord block write",
352   [0b001] = "OWord dual block write",
353   [0b010] = "media block write",
354   [0b011] = "DWord scattered write",
355   [0b100] = "RT write",
356   [0b101] = "streamed VB write",
357   [0b110] = "RT UNORM write", /* G45+ */
358   [0b111] = "flush render cache",
359};
360
361static const char *const dp_rc_msg_type_gfx6[16] = {
362   [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
363   [GFX6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
364   [GFX6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
365   [GFX6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read",
366   [GFX6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] =
367      "OWORD unaligned block read",
368   [GFX6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read",
369   [GFX6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write",
370   [GFX6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write",
371   [GFX6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] =
372      "OWORD dual block write",
373   [GFX6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write",
374   [GFX6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] =
375      "DWORD scattered write",
376   [GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write",
377   [GFX6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write",
378   [GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORM write",
379};
380
381static const char *const dp_rc_msg_type_gfx7[16] = {
382   [GFX7_DATAPORT_RC_MEDIA_BLOCK_READ] = "media block read",
383   [GFX7_DATAPORT_RC_TYPED_SURFACE_READ] = "typed surface read",
384   [GFX7_DATAPORT_RC_TYPED_ATOMIC_OP] = "typed atomic op",
385   [GFX7_DATAPORT_RC_MEMORY_FENCE] = "memory fence",
386   [GFX7_DATAPORT_RC_MEDIA_BLOCK_WRITE] = "media block write",
387   [GFX7_DATAPORT_RC_RENDER_TARGET_WRITE] = "RT write",
388   [GFX7_DATAPORT_RC_TYPED_SURFACE_WRITE] = "typed surface write"
389};
390
391static const char *const dp_rc_msg_type_gfx9[16] = {
392   [GFX9_DATAPORT_RC_RENDER_TARGET_WRITE] = "RT write",
393   [GFX9_DATAPORT_RC_RENDER_TARGET_READ] = "RT read"
394};
395
396static const char *const *
397dp_rc_msg_type(const struct intel_device_info *devinfo)
398{
399   return (devinfo->ver >= 9 ? dp_rc_msg_type_gfx9 :
400           devinfo->ver >= 7 ? dp_rc_msg_type_gfx7 :
401           devinfo->ver >= 6 ? dp_rc_msg_type_gfx6 :
402           dp_write_port_msg_type);
403}
404
405static const char *const m_rt_write_subtype[] = {
406   [0b000] = "SIMD16",
407   [0b001] = "SIMD16/RepData",
408   [0b010] = "SIMD8/DualSrcLow",
409   [0b011] = "SIMD8/DualSrcHigh",
410   [0b100] = "SIMD8",
411   [0b101] = "SIMD8/ImageWrite",   /* Gfx6+ */
412   [0b111] = "SIMD16/RepData-111", /* no idea how this is different than 1 */
413};
414
415static const char *const dp_dc0_msg_type_gfx7[16] = {
416   [GFX7_DATAPORT_DC_OWORD_BLOCK_READ] = "DC OWORD block read",
417   [GFX7_DATAPORT_DC_UNALIGNED_OWORD_BLOCK_READ] =
418      "DC unaligned OWORD block read",
419   [GFX7_DATAPORT_DC_OWORD_DUAL_BLOCK_READ] = "DC OWORD dual block read",
420   [GFX7_DATAPORT_DC_DWORD_SCATTERED_READ] = "DC DWORD scattered read",
421   [GFX7_DATAPORT_DC_BYTE_SCATTERED_READ] = "DC byte scattered read",
422   [GFX7_DATAPORT_DC_UNTYPED_SURFACE_READ] = "DC untyped surface read",
423   [GFX7_DATAPORT_DC_UNTYPED_ATOMIC_OP] = "DC untyped atomic",
424   [GFX7_DATAPORT_DC_MEMORY_FENCE] = "DC mfence",
425   [GFX7_DATAPORT_DC_OWORD_BLOCK_WRITE] = "DC OWORD block write",
426   [GFX7_DATAPORT_DC_OWORD_DUAL_BLOCK_WRITE] = "DC OWORD dual block write",
427   [GFX7_DATAPORT_DC_DWORD_SCATTERED_WRITE] = "DC DWORD scatterd write",
428   [GFX7_DATAPORT_DC_BYTE_SCATTERED_WRITE] = "DC byte scattered write",
429   [GFX7_DATAPORT_DC_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
430};
431
432static const char *const dp_oword_block_rw[8] = {
433      [BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW]  = "1-low",
434      [BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH] = "1-high",
435      [BRW_DATAPORT_OWORD_BLOCK_2_OWORDS]    = "2",
436      [BRW_DATAPORT_OWORD_BLOCK_4_OWORDS]    = "4",
437      [BRW_DATAPORT_OWORD_BLOCK_8_OWORDS]    = "8",
438};
439
440static const char *const dp_dc1_msg_type_hsw[32] = {
441   [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ] = "untyped surface read",
442   [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP] = "DC untyped atomic op",
443   [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2] =
444      "DC untyped 4x2 atomic op",
445   [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_READ] = "DC media block read",
446   [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ] = "DC typed surface read",
447   [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP] = "DC typed atomic",
448   [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2] = "DC typed 4x2 atomic op",
449   [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
450   [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_WRITE] = "DC media block write",
451   [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP] = "DC atomic counter op",
452   [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2] =
453      "DC 4x2 atomic counter op",
454   [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE] = "DC typed surface write",
455   [GFX9_DATAPORT_DC_PORT1_A64_SCATTERED_READ] = "DC A64 scattered read",
456   [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_READ] = "DC A64 untyped surface read",
457   [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_OP] = "DC A64 untyped atomic op",
458   [GFX9_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_READ] = "DC A64 oword block read",
459   [GFX9_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_WRITE] = "DC A64 oword block write",
460   [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_WRITE] = "DC A64 untyped surface write",
461   [GFX8_DATAPORT_DC_PORT1_A64_SCATTERED_WRITE] = "DC A64 scattered write",
462   [GFX9_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_FLOAT_OP] =
463      "DC untyped atomic float op",
464   [GFX9_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_FLOAT_OP] =
465      "DC A64 untyped atomic float op",
466   [GFX12_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_HALF_INT_OP] =
467      "DC A64 untyped atomic half-integer op",
468   [GFX12_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_HALF_FLOAT_OP] =
469      "DC A64 untyped atomic half-float op",
470};
471
472static const char *const aop[16] = {
473   [BRW_AOP_AND]    = "and",
474   [BRW_AOP_OR]     = "or",
475   [BRW_AOP_XOR]    = "xor",
476   [BRW_AOP_MOV]    = "mov",
477   [BRW_AOP_INC]    = "inc",
478   [BRW_AOP_DEC]    = "dec",
479   [BRW_AOP_ADD]    = "add",
480   [BRW_AOP_SUB]    = "sub",
481   [BRW_AOP_REVSUB] = "revsub",
482   [BRW_AOP_IMAX]   = "imax",
483   [BRW_AOP_IMIN]   = "imin",
484   [BRW_AOP_UMAX]   = "umax",
485   [BRW_AOP_UMIN]   = "umin",
486   [BRW_AOP_CMPWR]  = "cmpwr",
487   [BRW_AOP_PREDEC] = "predec",
488};
489
490static const char *const aop_float[5] = {
491   [BRW_AOP_FMAX]   = "fmax",
492   [BRW_AOP_FMIN]   = "fmin",
493   [BRW_AOP_FCMPWR] = "fcmpwr",
494   [BRW_AOP_FADD]   = "fadd",
495};
496
497static const char * const pixel_interpolator_msg_types[4] = {
498    [GFX7_PIXEL_INTERPOLATOR_LOC_SHARED_OFFSET] = "per_message_offset",
499    [GFX7_PIXEL_INTERPOLATOR_LOC_SAMPLE] = "sample_position",
500    [GFX7_PIXEL_INTERPOLATOR_LOC_CENTROID] = "centroid",
501    [GFX7_PIXEL_INTERPOLATOR_LOC_PER_SLOT_OFFSET] = "per_slot_offset",
502};
503
504static const char *const math_function[16] = {
505   [BRW_MATH_FUNCTION_INV]    = "inv",
506   [BRW_MATH_FUNCTION_LOG]    = "log",
507   [BRW_MATH_FUNCTION_EXP]    = "exp",
508   [BRW_MATH_FUNCTION_SQRT]   = "sqrt",
509   [BRW_MATH_FUNCTION_RSQ]    = "rsq",
510   [BRW_MATH_FUNCTION_SIN]    = "sin",
511   [BRW_MATH_FUNCTION_COS]    = "cos",
512   [BRW_MATH_FUNCTION_SINCOS] = "sincos",
513   [BRW_MATH_FUNCTION_FDIV]   = "fdiv",
514   [BRW_MATH_FUNCTION_POW]    = "pow",
515   [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
516   [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT]  = "intdiv",
517   [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
518   [GFX8_MATH_FUNCTION_INVM]  = "invm",
519   [GFX8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
520};
521
522static const char *const sync_function[16] = {
523   [TGL_SYNC_NOP] = "nop",
524   [TGL_SYNC_ALLRD] = "allrd",
525   [TGL_SYNC_ALLWR] = "allwr",
526   [TGL_SYNC_BAR] = "bar",
527   [TGL_SYNC_HOST] = "host",
528};
529
530static const char *const math_saturate[2] = {
531   [0] = "",
532   [1] = "sat"
533};
534
535static const char *const math_signed[2] = {
536   [0] = "",
537   [1] = "signed"
538};
539
540static const char *const math_scalar[2] = {
541   [0] = "",
542   [1] = "scalar"
543};
544
545static const char *const math_precision[2] = {
546   [0] = "",
547   [1] = "partial_precision"
548};
549
550static const char *const gfx5_urb_opcode[] = {
551   [0] = "urb_write",
552   [1] = "ff_sync",
553};
554
555static const char *const gfx7_urb_opcode[] = {
556   [BRW_URB_OPCODE_WRITE_HWORD] = "write HWord",
557   [BRW_URB_OPCODE_WRITE_OWORD] = "write OWord",
558   [BRW_URB_OPCODE_READ_HWORD] = "read HWord",
559   [BRW_URB_OPCODE_READ_OWORD] = "read OWord",
560   [GFX7_URB_OPCODE_ATOMIC_MOV] = "atomic mov",  /* Gfx7+ */
561   [GFX7_URB_OPCODE_ATOMIC_INC] = "atomic inc",  /* Gfx7+ */
562   [GFX8_URB_OPCODE_ATOMIC_ADD] = "atomic add",  /* Gfx8+ */
563   [GFX8_URB_OPCODE_SIMD8_WRITE] = "SIMD8 write", /* Gfx8+ */
564   [GFX8_URB_OPCODE_SIMD8_READ] = "SIMD8 read",  /* Gfx8+ */
565   [GFX125_URB_OPCODE_FENCE] = "fence",  /* Gfx12.5+ */
566   /* [10-15] - reserved */
567};
568
569static const char *const urb_swizzle[4] = {
570   [BRW_URB_SWIZZLE_NONE]       = "",
571   [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
572   [BRW_URB_SWIZZLE_TRANSPOSE]  = "transpose",
573};
574
575static const char *const urb_allocate[2] = {
576   [0] = "",
577   [1] = "allocate"
578};
579
580static const char *const urb_used[2] = {
581   [0] = "",
582   [1] = "used"
583};
584
585static const char *const urb_complete[2] = {
586   [0] = "",
587   [1] = "complete"
588};
589
590static const char *const gfx5_sampler_msg_type[] = {
591   [GFX5_SAMPLER_MESSAGE_SAMPLE]              = "sample",
592   [GFX5_SAMPLER_MESSAGE_SAMPLE_BIAS]         = "sample_b",
593   [GFX5_SAMPLER_MESSAGE_SAMPLE_LOD]          = "sample_l",
594   [GFX5_SAMPLER_MESSAGE_SAMPLE_COMPARE]      = "sample_c",
595   [GFX5_SAMPLER_MESSAGE_SAMPLE_DERIVS]       = "sample_d",
596   [GFX5_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE] = "sample_b_c",
597   [GFX5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE]  = "sample_l_c",
598   [GFX5_SAMPLER_MESSAGE_SAMPLE_LD]           = "ld",
599   [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4]      = "gather4",
600   [GFX5_SAMPLER_MESSAGE_LOD]                 = "lod",
601   [GFX5_SAMPLER_MESSAGE_SAMPLE_RESINFO]      = "resinfo",
602   [GFX6_SAMPLER_MESSAGE_SAMPLE_SAMPLEINFO]   = "sampleinfo",
603   [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_C]    = "gather4_c",
604   [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO]   = "gather4_po",
605   [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO_C] = "gather4_po_c",
606   [HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE] = "sample_d_c",
607   [GFX9_SAMPLER_MESSAGE_SAMPLE_LZ]           = "sample_lz",
608   [GFX9_SAMPLER_MESSAGE_SAMPLE_C_LZ]         = "sample_c_lz",
609   [GFX9_SAMPLER_MESSAGE_SAMPLE_LD_LZ]        = "ld_lz",
610   [GFX9_SAMPLER_MESSAGE_SAMPLE_LD2DMS_W]     = "ld2dms_w",
611   [GFX7_SAMPLER_MESSAGE_SAMPLE_LD_MCS]       = "ld_mcs",
612   [GFX7_SAMPLER_MESSAGE_SAMPLE_LD2DMS]       = "ld2dms",
613   [GFX7_SAMPLER_MESSAGE_SAMPLE_LD2DSS]       = "ld2dss",
614};
615
616static const char *const gfx5_sampler_simd_mode[4] = {
617   [BRW_SAMPLER_SIMD_MODE_SIMD4X2]   = "SIMD4x2",
618   [BRW_SAMPLER_SIMD_MODE_SIMD8]     = "SIMD8",
619   [BRW_SAMPLER_SIMD_MODE_SIMD16]    = "SIMD16",
620   [BRW_SAMPLER_SIMD_MODE_SIMD32_64] = "SIMD32/64",
621};
622
623static const char *const sampler_target_format[4] = {
624   [0] = "F",
625   [2] = "UD",
626   [3] = "D"
627};
628
629static const char *const lsc_operation[] = {
630   [LSC_OP_LOAD]            = "load",
631   [LSC_OP_LOAD_CMASK]      = "load_cmask",
632   [LSC_OP_STORE]           = "store",
633   [LSC_OP_STORE_CMASK]     = "store_cmask",
634   [LSC_OP_FENCE]           = "fence",
635   [LSC_OP_ATOMIC_INC]      = "atomic_inc",
636   [LSC_OP_ATOMIC_DEC]      = "atomic_dec",
637   [LSC_OP_ATOMIC_LOAD]     = "atomic_load",
638   [LSC_OP_ATOMIC_STORE]    = "atomic_store",
639   [LSC_OP_ATOMIC_ADD]      = "atomic_add",
640   [LSC_OP_ATOMIC_SUB]      = "atomic_sub",
641   [LSC_OP_ATOMIC_MIN]      = "atomic_min",
642   [LSC_OP_ATOMIC_MAX]      = "atomic_max",
643   [LSC_OP_ATOMIC_UMIN]     = "atomic_umin",
644   [LSC_OP_ATOMIC_UMAX]     = "atomic_umax",
645   [LSC_OP_ATOMIC_CMPXCHG]  = "atomic_cmpxchg",
646   [LSC_OP_ATOMIC_FADD]     = "atomic_fadd",
647   [LSC_OP_ATOMIC_FSUB]     = "atomic_fsub",
648   [LSC_OP_ATOMIC_FMIN]     = "atomic_fmin",
649   [LSC_OP_ATOMIC_FMAX]     = "atomic_fmax",
650   [LSC_OP_ATOMIC_FCMPXCHG] = "atomic_fcmpxchg",
651   [LSC_OP_ATOMIC_AND]      = "atomic_and",
652   [LSC_OP_ATOMIC_OR]       = "atomic_or",
653   [LSC_OP_ATOMIC_XOR]      = "atomic_xor",
654};
655
656static const char *const lsc_addr_surface_type[] = {
657   [LSC_ADDR_SURFTYPE_FLAT] = "flat",
658   [LSC_ADDR_SURFTYPE_BSS]  = "bss",
659   [LSC_ADDR_SURFTYPE_SS]   = "ss",
660   [LSC_ADDR_SURFTYPE_BTI]  = "bti",
661};
662
663static const char* const lsc_fence_scope[] = {
664   [LSC_FENCE_THREADGROUP]     = "threadgroup",
665   [LSC_FENCE_LOCAL]           = "local",
666   [LSC_FENCE_TILE]            = "tile",
667   [LSC_FENCE_GPU]             = "gpu",
668   [LSC_FENCE_ALL_GPU]         = "all_gpu",
669   [LSC_FENCE_SYSTEM_RELEASE]  = "system_release",
670   [LSC_FENCE_SYSTEM_ACQUIRE]  = "system_acquire",
671};
672
673static const char* const lsc_flush_type[] = {
674   [LSC_FLUSH_TYPE_NONE]       = "none",
675   [LSC_FLUSH_TYPE_EVICT]      = "evict",
676   [LSC_FLUSH_TYPE_INVALIDATE] = "invalidate",
677   [LSC_FLUSH_TYPE_DISCARD]    = "discard",
678   [LSC_FLUSH_TYPE_CLEAN]      = "clean",
679   [LSC_FLUSH_TYPE_L3ONLY]     = "l3only",
680};
681
682static const char* const lsc_addr_size[] = {
683   [LSC_ADDR_SIZE_A16] = "a16",
684   [LSC_ADDR_SIZE_A32] = "a32",
685   [LSC_ADDR_SIZE_A64] = "a64",
686};
687
688static const char* const lsc_backup_fence_routing[] = {
689   [LSC_NORMAL_ROUTING]  = "normal_routing",
690   [LSC_ROUTE_TO_LSC]    = "route_to_lsc",
691};
692
693static const char* const lsc_data_size[] = {
694   [LSC_DATA_SIZE_D8]      = "d8",
695   [LSC_DATA_SIZE_D16]     = "d16",
696   [LSC_DATA_SIZE_D32]     = "d32",
697   [LSC_DATA_SIZE_D64]     = "d64",
698   [LSC_DATA_SIZE_D8U32]   = "d8u32",
699   [LSC_DATA_SIZE_D16U32]  = "d16u32",
700   [LSC_DATA_SIZE_D16BF32] = "d16bf32",
701};
702
703static const char* const lsc_vect_size_str[] = {
704   [LSC_VECT_SIZE_V1] = "V1",
705   [LSC_VECT_SIZE_V2] = "V2",
706   [LSC_VECT_SIZE_V3] = "V3",
707   [LSC_VECT_SIZE_V4] = "V4",
708   [LSC_VECT_SIZE_V8] = "V8",
709   [LSC_VECT_SIZE_V16] = "V16",
710   [LSC_VECT_SIZE_V32] = "V32",
711   [LSC_VECT_SIZE_V64] = "V64",
712};
713
714static const char* const lsc_cmask_str[] = {
715   [LSC_CMASK_X]      = "x",
716   [LSC_CMASK_Y]      = "y",
717   [LSC_CMASK_XY]     = "xy",
718   [LSC_CMASK_Z]      = "z",
719   [LSC_CMASK_XZ]     = "xz",
720   [LSC_CMASK_YZ]     = "yz",
721   [LSC_CMASK_XYZ]    = "xyz",
722   [LSC_CMASK_W]      = "w",
723   [LSC_CMASK_XW]     = "xw",
724   [LSC_CMASK_YW]     = "yw",
725   [LSC_CMASK_XYW]    = "xyw",
726   [LSC_CMASK_ZW]     = "zw",
727   [LSC_CMASK_XZW]    = "xzw",
728   [LSC_CMASK_YZW]    = "yzw",
729   [LSC_CMASK_XYZW]   = "xyzw",
730};
731
732static const char* const lsc_cache_load[] = {
733   [LSC_CACHE_LOAD_L1STATE_L3MOCS]   = "L1STATE_L3MOCS",
734   [LSC_CACHE_LOAD_L1UC_L3UC]        = "L1UC_L3UC",
735   [LSC_CACHE_LOAD_L1UC_L3C]         = "L1UC_L3C",
736   [LSC_CACHE_LOAD_L1C_L3UC]         = "L1C_L3UC",
737   [LSC_CACHE_LOAD_L1C_L3C]          = "L1C_L3C",
738   [LSC_CACHE_LOAD_L1S_L3UC]         = "L1S_L3UC",
739   [LSC_CACHE_LOAD_L1S_L3C]          = "L1S_L3C",
740   [LSC_CACHE_LOAD_L1IAR_L3C]        = "L1IAR_L3C",
741};
742
743static const char* const lsc_cache_store[] = {
744   [LSC_CACHE_STORE_L1STATE_L3MOCS]  = "L1STATE_L3MOCS",
745   [LSC_CACHE_STORE_L1UC_L3UC]       = "L1UC_L3UC",
746   [LSC_CACHE_STORE_L1UC_L3WB]       = "L1UC_L3WB",
747   [LSC_CACHE_STORE_L1WT_L3UC]       = "L1WT_L3UC",
748   [LSC_CACHE_STORE_L1WT_L3WB]       = "L1WT_L3WB",
749   [LSC_CACHE_STORE_L1S_L3UC]        = "L1S_L3UC",
750   [LSC_CACHE_STORE_L1S_L3WB]        = "L1S_L3WB",
751   [LSC_CACHE_STORE_L1WB_L3WB]       = "L1WB_L3WB",
752};
753
754static int column;
755
756static int
757string(FILE *file, const char *string)
758{
759   fputs(string, file);
760   column += strlen(string);
761   return 0;
762}
763
764static int
765format(FILE *f, const char *format, ...) PRINTFLIKE(2, 3);
766
767static int
768format(FILE *f, const char *format, ...)
769{
770   char buf[1024];
771   va_list args;
772   va_start(args, format);
773
774   vsnprintf(buf, sizeof(buf) - 1, format, args);
775   va_end(args);
776   string(f, buf);
777   return 0;
778}
779
780static int
781newline(FILE *f)
782{
783   putc('\n', f);
784   column = 0;
785   return 0;
786}
787
788static int
789pad(FILE *f, int c)
790{
791   do
792      string(f, " ");
793   while (column < c);
794   return 0;
795}
796
797static int
798control(FILE *file, const char *name, const char *const ctrl[],
799        unsigned id, int *space)
800{
801   if (!ctrl[id]) {
802      fprintf(file, "*** invalid %s value %d ", name, id);
803      return 1;
804   }
805   if (ctrl[id][0]) {
806      if (space && *space)
807         string(file, " ");
808      string(file, ctrl[id]);
809      if (space)
810         *space = 1;
811   }
812   return 0;
813}
814
815static int
816print_opcode(FILE *file, const struct intel_device_info *devinfo,
817             enum opcode id)
818{
819   const struct opcode_desc *desc = brw_opcode_desc(devinfo, id);
820   if (!desc) {
821      format(file, "*** invalid opcode value %d ", id);
822      return 1;
823   }
824   string(file, desc->name);
825   return 0;
826}
827
828static int
829reg(FILE *file, unsigned _reg_file, unsigned _reg_nr)
830{
831   int err = 0;
832
833   /* Clear the Compr4 instruction compression bit. */
834   if (_reg_file == BRW_MESSAGE_REGISTER_FILE)
835      _reg_nr &= ~BRW_MRF_COMPR4;
836
837   if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
838      switch (_reg_nr & 0xf0) {
839      case BRW_ARF_NULL:
840         string(file, "null");
841         break;
842      case BRW_ARF_ADDRESS:
843         format(file, "a%d", _reg_nr & 0x0f);
844         break;
845      case BRW_ARF_ACCUMULATOR:
846         format(file, "acc%d", _reg_nr & 0x0f);
847         break;
848      case BRW_ARF_FLAG:
849         format(file, "f%d", _reg_nr & 0x0f);
850         break;
851      case BRW_ARF_MASK:
852         format(file, "mask%d", _reg_nr & 0x0f);
853         break;
854      case BRW_ARF_MASK_STACK:
855         format(file, "ms%d", _reg_nr & 0x0f);
856         break;
857      case BRW_ARF_MASK_STACK_DEPTH:
858         format(file, "msd%d", _reg_nr & 0x0f);
859         break;
860      case BRW_ARF_STATE:
861         format(file, "sr%d", _reg_nr & 0x0f);
862         break;
863      case BRW_ARF_CONTROL:
864         format(file, "cr%d", _reg_nr & 0x0f);
865         break;
866      case BRW_ARF_NOTIFICATION_COUNT:
867         format(file, "n%d", _reg_nr & 0x0f);
868         break;
869      case BRW_ARF_IP:
870         string(file, "ip");
871         return -1;
872         break;
873      case BRW_ARF_TDR:
874         format(file, "tdr0");
875         return -1;
876      case BRW_ARF_TIMESTAMP:
877         format(file, "tm%d", _reg_nr & 0x0f);
878         break;
879      default:
880         format(file, "ARF%d", _reg_nr);
881         break;
882      }
883   } else {
884      err |= control(file, "src reg file", reg_file, _reg_file, NULL);
885      format(file, "%d", _reg_nr);
886   }
887   return err;
888}
889
890static int
891dest(FILE *file, const struct intel_device_info *devinfo, const brw_inst *inst)
892{
893   enum brw_reg_type type = brw_inst_dst_type(devinfo, inst);
894   unsigned elem_size = brw_reg_type_to_size(type);
895   int err = 0;
896
897   if (is_split_send(devinfo, brw_inst_opcode(devinfo, inst))) {
898      /* These are fixed for split sends */
899      type = BRW_REGISTER_TYPE_UD;
900      elem_size = 4;
901      if (devinfo->ver >= 12) {
902         err |= reg(file, brw_inst_send_dst_reg_file(devinfo, inst),
903                    brw_inst_dst_da_reg_nr(devinfo, inst));
904         string(file, brw_reg_type_to_letters(type));
905      } else if (brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
906         err |= reg(file, brw_inst_send_dst_reg_file(devinfo, inst),
907                    brw_inst_dst_da_reg_nr(devinfo, inst));
908         unsigned subreg_nr = brw_inst_dst_da16_subreg_nr(devinfo, inst);
909         if (subreg_nr)
910            format(file, ".%u", subreg_nr);
911         string(file, brw_reg_type_to_letters(type));
912      } else {
913         string(file, "g[a0");
914         if (brw_inst_dst_ia_subreg_nr(devinfo, inst))
915            format(file, ".%"PRIu64, brw_inst_dst_ia_subreg_nr(devinfo, inst) /
916                   elem_size);
917         if (brw_inst_send_dst_ia16_addr_imm(devinfo, inst))
918            format(file, " %d", brw_inst_send_dst_ia16_addr_imm(devinfo, inst));
919         string(file, "]<");
920         string(file, brw_reg_type_to_letters(type));
921      }
922   } else if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
923      if (brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
924         err |= reg(file, brw_inst_dst_reg_file(devinfo, inst),
925                    brw_inst_dst_da_reg_nr(devinfo, inst));
926         if (err == -1)
927            return 0;
928         if (brw_inst_dst_da1_subreg_nr(devinfo, inst))
929            format(file, ".%"PRIu64, brw_inst_dst_da1_subreg_nr(devinfo, inst) /
930                   elem_size);
931         string(file, "<");
932         err |= control(file, "horiz stride", horiz_stride,
933                        brw_inst_dst_hstride(devinfo, inst), NULL);
934         string(file, ">");
935         string(file, brw_reg_type_to_letters(type));
936      } else {
937         string(file, "g[a0");
938         if (brw_inst_dst_ia_subreg_nr(devinfo, inst))
939            format(file, ".%"PRIu64, brw_inst_dst_ia_subreg_nr(devinfo, inst) /
940                   elem_size);
941         if (brw_inst_dst_ia1_addr_imm(devinfo, inst))
942            format(file, " %d", brw_inst_dst_ia1_addr_imm(devinfo, inst));
943         string(file, "]<");
944         err |= control(file, "horiz stride", horiz_stride,
945                        brw_inst_dst_hstride(devinfo, inst), NULL);
946         string(file, ">");
947         string(file, brw_reg_type_to_letters(type));
948      }
949   } else {
950      if (brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
951         err |= reg(file, brw_inst_dst_reg_file(devinfo, inst),
952                    brw_inst_dst_da_reg_nr(devinfo, inst));
953         if (err == -1)
954            return 0;
955         if (brw_inst_dst_da16_subreg_nr(devinfo, inst))
956            format(file, ".%u", 16 / elem_size);
957         string(file, "<1>");
958         err |= control(file, "writemask", writemask,
959                        brw_inst_da16_writemask(devinfo, inst), NULL);
960         string(file, brw_reg_type_to_letters(type));
961      } else {
962         err = 1;
963         string(file, "Indirect align16 address mode not supported");
964      }
965   }
966
967   return 0;
968}
969
970static int
971dest_3src(FILE *file, const struct intel_device_info *devinfo,
972          const brw_inst *inst)
973{
974   bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
975   int err = 0;
976   uint32_t reg_file;
977   unsigned subreg_nr;
978   enum brw_reg_type type;
979
980   if (devinfo->ver < 10 && is_align1)
981      return 0;
982
983   if (devinfo->ver == 6 && brw_inst_3src_a16_dst_reg_file(devinfo, inst))
984      reg_file = BRW_MESSAGE_REGISTER_FILE;
985   else if (devinfo->ver >= 12)
986      reg_file = brw_inst_3src_a1_dst_reg_file(devinfo, inst);
987   else if (is_align1 && brw_inst_3src_a1_dst_reg_file(devinfo, inst))
988      reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
989   else
990      reg_file = BRW_GENERAL_REGISTER_FILE;
991
992   err |= reg(file, reg_file, brw_inst_3src_dst_reg_nr(devinfo, inst));
993   if (err == -1)
994      return 0;
995
996   if (is_align1) {
997      type = brw_inst_3src_a1_dst_type(devinfo, inst);
998      subreg_nr = brw_inst_3src_a1_dst_subreg_nr(devinfo, inst);
999   } else {
1000      type = brw_inst_3src_a16_dst_type(devinfo, inst);
1001      subreg_nr = brw_inst_3src_a16_dst_subreg_nr(devinfo, inst) * 4;
1002   }
1003   subreg_nr /= brw_reg_type_to_size(type);
1004
1005   if (subreg_nr)
1006      format(file, ".%u", subreg_nr);
1007   string(file, "<1>");
1008
1009   if (!is_align1) {
1010      err |= control(file, "writemask", writemask,
1011                     brw_inst_3src_a16_dst_writemask(devinfo, inst), NULL);
1012   }
1013   string(file, brw_reg_type_to_letters(type));
1014
1015   return 0;
1016}
1017
1018static int
1019src_align1_region(FILE *file,
1020                  unsigned _vert_stride, unsigned _width,
1021                  unsigned _horiz_stride)
1022{
1023   int err = 0;
1024   string(file, "<");
1025   err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
1026   string(file, ",");
1027   err |= control(file, "width", width, _width, NULL);
1028   string(file, ",");
1029   err |= control(file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
1030   string(file, ">");
1031   return err;
1032}
1033
1034static int
1035src_da1(FILE *file,
1036        const struct intel_device_info *devinfo,
1037        unsigned opcode,
1038        enum brw_reg_type type, unsigned _reg_file,
1039        unsigned _vert_stride, unsigned _width, unsigned _horiz_stride,
1040        unsigned reg_num, unsigned sub_reg_num, unsigned __abs,
1041        unsigned _negate)
1042{
1043   int err = 0;
1044
1045   if (devinfo->ver >= 8 && is_logic_instruction(opcode))
1046      err |= control(file, "bitnot", m_bitnot, _negate, NULL);
1047   else
1048      err |= control(file, "negate", m_negate, _negate, NULL);
1049
1050   err |= control(file, "abs", _abs, __abs, NULL);
1051
1052   err |= reg(file, _reg_file, reg_num);
1053   if (err == -1)
1054      return 0;
1055   if (sub_reg_num) {
1056      unsigned elem_size = brw_reg_type_to_size(type);
1057      format(file, ".%d", sub_reg_num / elem_size);   /* use formal style like spec */
1058   }
1059   src_align1_region(file, _vert_stride, _width, _horiz_stride);
1060   string(file, brw_reg_type_to_letters(type));
1061   return err;
1062}
1063
1064static int
1065src_ia1(FILE *file,
1066        const struct intel_device_info *devinfo,
1067        unsigned opcode,
1068        enum brw_reg_type type,
1069        int _addr_imm,
1070        unsigned _addr_subreg_nr,
1071        unsigned _negate,
1072        unsigned __abs,
1073        unsigned _horiz_stride, unsigned _width, unsigned _vert_stride)
1074{
1075   int err = 0;
1076
1077   if (devinfo->ver >= 8 && is_logic_instruction(opcode))
1078      err |= control(file, "bitnot", m_bitnot, _negate, NULL);
1079   else
1080      err |= control(file, "negate", m_negate, _negate, NULL);
1081
1082   err |= control(file, "abs", _abs, __abs, NULL);
1083
1084   string(file, "g[a0");
1085   if (_addr_subreg_nr)
1086      format(file, ".%d", _addr_subreg_nr);
1087   if (_addr_imm)
1088      format(file, " %d", _addr_imm);
1089   string(file, "]");
1090   src_align1_region(file, _vert_stride, _width, _horiz_stride);
1091   string(file, brw_reg_type_to_letters(type));
1092   return err;
1093}
1094
1095static int
1096src_swizzle(FILE *file, unsigned swiz)
1097{
1098   unsigned x = BRW_GET_SWZ(swiz, BRW_CHANNEL_X);
1099   unsigned y = BRW_GET_SWZ(swiz, BRW_CHANNEL_Y);
1100   unsigned z = BRW_GET_SWZ(swiz, BRW_CHANNEL_Z);
1101   unsigned w = BRW_GET_SWZ(swiz, BRW_CHANNEL_W);
1102   int err = 0;
1103
1104   if (x == y && x == z && x == w) {
1105      string(file, ".");
1106      err |= control(file, "channel select", chan_sel, x, NULL);
1107   } else if (swiz != BRW_SWIZZLE_XYZW) {
1108      string(file, ".");
1109      err |= control(file, "channel select", chan_sel, x, NULL);
1110      err |= control(file, "channel select", chan_sel, y, NULL);
1111      err |= control(file, "channel select", chan_sel, z, NULL);
1112      err |= control(file, "channel select", chan_sel, w, NULL);
1113   }
1114   return err;
1115}
1116
1117static int
1118src_da16(FILE *file,
1119         const struct intel_device_info *devinfo,
1120         unsigned opcode,
1121         enum brw_reg_type type,
1122         unsigned _reg_file,
1123         unsigned _vert_stride,
1124         unsigned _reg_nr,
1125         unsigned _subreg_nr,
1126         unsigned __abs,
1127         unsigned _negate,
1128         unsigned swz_x, unsigned swz_y, unsigned swz_z, unsigned swz_w)
1129{
1130   int err = 0;
1131
1132   if (devinfo->ver >= 8 && is_logic_instruction(opcode))
1133      err |= control(file, "bitnot", m_bitnot, _negate, NULL);
1134   else
1135      err |= control(file, "negate", m_negate, _negate, NULL);
1136
1137   err |= control(file, "abs", _abs, __abs, NULL);
1138
1139   err |= reg(file, _reg_file, _reg_nr);
1140   if (err == -1)
1141      return 0;
1142   if (_subreg_nr) {
1143      unsigned elem_size = brw_reg_type_to_size(type);
1144
1145      /* bit4 for subreg number byte addressing. Make this same meaning as
1146         in da1 case, so output looks consistent. */
1147      format(file, ".%d", 16 / elem_size);
1148   }
1149   string(file, "<");
1150   err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
1151   string(file, ">");
1152   err |= src_swizzle(file, BRW_SWIZZLE4(swz_x, swz_y, swz_z, swz_w));
1153   string(file, brw_reg_type_to_letters(type));
1154   return err;
1155}
1156
1157static enum brw_vertical_stride
1158vstride_from_align1_3src_vstride(const struct intel_device_info *devinfo,
1159                                 enum gfx10_align1_3src_vertical_stride vstride)
1160{
1161   switch (vstride) {
1162   case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_0: return BRW_VERTICAL_STRIDE_0;
1163   case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_2:
1164      if (devinfo->ver >= 12)
1165         return BRW_VERTICAL_STRIDE_1;
1166      else
1167         return BRW_VERTICAL_STRIDE_2;
1168   case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_4: return BRW_VERTICAL_STRIDE_4;
1169   case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_8: return BRW_VERTICAL_STRIDE_8;
1170   default:
1171      unreachable("not reached");
1172   }
1173}
1174
1175static enum brw_horizontal_stride
1176hstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)
1177{
1178   switch (hstride) {
1179   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return BRW_HORIZONTAL_STRIDE_0;
1180   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return BRW_HORIZONTAL_STRIDE_1;
1181   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return BRW_HORIZONTAL_STRIDE_2;
1182   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return BRW_HORIZONTAL_STRIDE_4;
1183   default:
1184      unreachable("not reached");
1185   }
1186}
1187
1188static enum brw_vertical_stride
1189vstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)
1190{
1191   switch (hstride) {
1192   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return BRW_VERTICAL_STRIDE_0;
1193   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return BRW_VERTICAL_STRIDE_1;
1194   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return BRW_VERTICAL_STRIDE_2;
1195   case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return BRW_VERTICAL_STRIDE_4;
1196   default:
1197      unreachable("not reached");
1198   }
1199}
1200
1201/* From "GFX10 Regioning Rules for Align1 Ternary Operations" in the
1202 * "Register Region Restrictions" documentation
1203 */
1204static enum brw_width
1205implied_width(enum brw_vertical_stride _vert_stride,
1206              enum brw_horizontal_stride _horiz_stride)
1207{
1208   /* "1. Width is 1 when Vertical and Horizontal Strides are both zero." */
1209   if (_vert_stride == BRW_VERTICAL_STRIDE_0 &&
1210       _horiz_stride == BRW_HORIZONTAL_STRIDE_0) {
1211      return BRW_WIDTH_1;
1212
1213   /* "2. Width is equal to vertical stride when Horizontal Stride is zero." */
1214   } else if (_horiz_stride == BRW_HORIZONTAL_STRIDE_0) {
1215      switch (_vert_stride) {
1216      case BRW_VERTICAL_STRIDE_2: return BRW_WIDTH_2;
1217      case BRW_VERTICAL_STRIDE_4: return BRW_WIDTH_4;
1218      case BRW_VERTICAL_STRIDE_8: return BRW_WIDTH_8;
1219      case BRW_VERTICAL_STRIDE_0:
1220      default:
1221         unreachable("not reached");
1222      }
1223
1224   } else {
1225      /* FINISHME: Implement these: */
1226
1227      /* "3. Width is equal to Vertical Stride/Horizontal Stride when both
1228       *     Strides are non-zero.
1229       *
1230       *  4. Vertical Stride must not be zero if Horizontal Stride is non-zero.
1231       *     This implies Vertical Stride is always greater than Horizontal
1232       *     Stride."
1233       *
1234       * Given these statements and the knowledge that the stride and width
1235       * values are encoded in logarithmic form, we can perform the division
1236       * by just subtracting.
1237       */
1238      return _vert_stride - _horiz_stride;
1239   }
1240}
1241
1242static int
1243src0_3src(FILE *file, const struct intel_device_info *devinfo,
1244          const brw_inst *inst)
1245{
1246   int err = 0;
1247   unsigned reg_nr, subreg_nr;
1248   enum brw_reg_file _file;
1249   enum brw_reg_type type;
1250   enum brw_vertical_stride _vert_stride;
1251   enum brw_width _width;
1252   enum brw_horizontal_stride _horiz_stride;
1253   bool is_scalar_region;
1254   bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1255
1256   if (devinfo->ver < 10 && is_align1)
1257      return 0;
1258
1259   if (is_align1) {
1260      if (devinfo->ver >= 12 && !brw_inst_3src_a1_src0_is_imm(devinfo, inst)) {
1261         _file = brw_inst_3src_a1_src0_reg_file(devinfo, inst);
1262      } else if (brw_inst_3src_a1_src0_reg_file(devinfo, inst) ==
1263                 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1264         _file = BRW_GENERAL_REGISTER_FILE;
1265      } else if (brw_inst_3src_a1_src0_type(devinfo, inst) ==
1266                 BRW_REGISTER_TYPE_NF) {
1267         _file = BRW_ARCHITECTURE_REGISTER_FILE;
1268      } else {
1269         _file = BRW_IMMEDIATE_VALUE;
1270         uint16_t imm_val = brw_inst_3src_a1_src0_imm(devinfo, inst);
1271         enum brw_reg_type type = brw_inst_3src_a1_src0_type(devinfo, inst);
1272
1273         if (type == BRW_REGISTER_TYPE_W) {
1274            format(file, "%dW", imm_val);
1275         } else if (type == BRW_REGISTER_TYPE_UW) {
1276            format(file, "0x%04xUW", imm_val);
1277         } else if (type == BRW_REGISTER_TYPE_HF) {
1278            format(file, "0x%04xHF", imm_val);
1279         }
1280         return 0;
1281      }
1282
1283      reg_nr = brw_inst_3src_src0_reg_nr(devinfo, inst);
1284      subreg_nr = brw_inst_3src_a1_src0_subreg_nr(devinfo, inst);
1285      type = brw_inst_3src_a1_src0_type(devinfo, inst);
1286      _vert_stride = vstride_from_align1_3src_vstride(
1287         devinfo, brw_inst_3src_a1_src0_vstride(devinfo, inst));
1288      _horiz_stride = hstride_from_align1_3src_hstride(
1289                         brw_inst_3src_a1_src0_hstride(devinfo, inst));
1290      _width = implied_width(_vert_stride, _horiz_stride);
1291   } else {
1292      _file = BRW_GENERAL_REGISTER_FILE;
1293      reg_nr = brw_inst_3src_src0_reg_nr(devinfo, inst);
1294      subreg_nr = brw_inst_3src_a16_src0_subreg_nr(devinfo, inst) * 4;
1295      type = brw_inst_3src_a16_src_type(devinfo, inst);
1296
1297      if (brw_inst_3src_a16_src0_rep_ctrl(devinfo, inst)) {
1298         _vert_stride = BRW_VERTICAL_STRIDE_0;
1299         _width = BRW_WIDTH_1;
1300         _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1301      } else {
1302         _vert_stride = BRW_VERTICAL_STRIDE_4;
1303         _width = BRW_WIDTH_4;
1304         _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1305      }
1306   }
1307   is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1308                      _width == BRW_WIDTH_1 &&
1309                      _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1310
1311   subreg_nr /= brw_reg_type_to_size(type);
1312
1313   err |= control(file, "negate", m_negate,
1314                  brw_inst_3src_src0_negate(devinfo, inst), NULL);
1315   err |= control(file, "abs", _abs, brw_inst_3src_src0_abs(devinfo, inst), NULL);
1316
1317   err |= reg(file, _file, reg_nr);
1318   if (err == -1)
1319      return 0;
1320   if (subreg_nr || is_scalar_region)
1321      format(file, ".%d", subreg_nr);
1322   src_align1_region(file, _vert_stride, _width, _horiz_stride);
1323   if (!is_scalar_region && !is_align1)
1324      err |= src_swizzle(file, brw_inst_3src_a16_src0_swizzle(devinfo, inst));
1325   string(file, brw_reg_type_to_letters(type));
1326   return err;
1327}
1328
1329static int
1330src1_3src(FILE *file, const struct intel_device_info *devinfo,
1331          const brw_inst *inst)
1332{
1333   int err = 0;
1334   unsigned reg_nr, subreg_nr;
1335   enum brw_reg_file _file;
1336   enum brw_reg_type type;
1337   enum brw_vertical_stride _vert_stride;
1338   enum brw_width _width;
1339   enum brw_horizontal_stride _horiz_stride;
1340   bool is_scalar_region;
1341   bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1342
1343   if (devinfo->ver < 10 && is_align1)
1344      return 0;
1345
1346   if (is_align1) {
1347      if (devinfo->ver >= 12) {
1348         _file = brw_inst_3src_a1_src1_reg_file(devinfo, inst);
1349      } else if (brw_inst_3src_a1_src1_reg_file(devinfo, inst) ==
1350                 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1351         _file = BRW_GENERAL_REGISTER_FILE;
1352      } else {
1353         _file = BRW_ARCHITECTURE_REGISTER_FILE;
1354      }
1355
1356      reg_nr = brw_inst_3src_src1_reg_nr(devinfo, inst);
1357      subreg_nr = brw_inst_3src_a1_src1_subreg_nr(devinfo, inst);
1358      type = brw_inst_3src_a1_src1_type(devinfo, inst);
1359
1360      _vert_stride = vstride_from_align1_3src_vstride(
1361         devinfo, brw_inst_3src_a1_src1_vstride(devinfo, inst));
1362      _horiz_stride = hstride_from_align1_3src_hstride(
1363                         brw_inst_3src_a1_src1_hstride(devinfo, inst));
1364      _width = implied_width(_vert_stride, _horiz_stride);
1365   } else {
1366      _file = BRW_GENERAL_REGISTER_FILE;
1367      reg_nr = brw_inst_3src_src1_reg_nr(devinfo, inst);
1368      subreg_nr = brw_inst_3src_a16_src1_subreg_nr(devinfo, inst) * 4;
1369      type = brw_inst_3src_a16_src_type(devinfo, inst);
1370
1371      if (brw_inst_3src_a16_src1_rep_ctrl(devinfo, inst)) {
1372         _vert_stride = BRW_VERTICAL_STRIDE_0;
1373         _width = BRW_WIDTH_1;
1374         _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1375      } else {
1376         _vert_stride = BRW_VERTICAL_STRIDE_4;
1377         _width = BRW_WIDTH_4;
1378         _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1379      }
1380   }
1381   is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1382                      _width == BRW_WIDTH_1 &&
1383                      _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1384
1385   subreg_nr /= brw_reg_type_to_size(type);
1386
1387   err |= control(file, "negate", m_negate,
1388                  brw_inst_3src_src1_negate(devinfo, inst), NULL);
1389   err |= control(file, "abs", _abs, brw_inst_3src_src1_abs(devinfo, inst), NULL);
1390
1391   err |= reg(file, _file, reg_nr);
1392   if (err == -1)
1393      return 0;
1394   if (subreg_nr || is_scalar_region)
1395      format(file, ".%d", subreg_nr);
1396   src_align1_region(file, _vert_stride, _width, _horiz_stride);
1397   if (!is_scalar_region && !is_align1)
1398      err |= src_swizzle(file, brw_inst_3src_a16_src1_swizzle(devinfo, inst));
1399   string(file, brw_reg_type_to_letters(type));
1400   return err;
1401}
1402
1403static int
1404src2_3src(FILE *file, const struct intel_device_info *devinfo,
1405          const brw_inst *inst)
1406{
1407   int err = 0;
1408   unsigned reg_nr, subreg_nr;
1409   enum brw_reg_file _file;
1410   enum brw_reg_type type;
1411   enum brw_vertical_stride _vert_stride;
1412   enum brw_width _width;
1413   enum brw_horizontal_stride _horiz_stride;
1414   bool is_scalar_region;
1415   bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1416
1417   if (devinfo->ver < 10 && is_align1)
1418      return 0;
1419
1420   if (is_align1) {
1421      if (devinfo->ver >= 12 && !brw_inst_3src_a1_src2_is_imm(devinfo, inst)) {
1422         _file = brw_inst_3src_a1_src2_reg_file(devinfo, inst);
1423      } else if (brw_inst_3src_a1_src2_reg_file(devinfo, inst) ==
1424                 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1425         _file = BRW_GENERAL_REGISTER_FILE;
1426      } else {
1427         _file = BRW_IMMEDIATE_VALUE;
1428         uint16_t imm_val = brw_inst_3src_a1_src2_imm(devinfo, inst);
1429         enum brw_reg_type type = brw_inst_3src_a1_src2_type(devinfo, inst);
1430
1431         if (type == BRW_REGISTER_TYPE_W) {
1432            format(file, "%dW", imm_val);
1433         } else if (type == BRW_REGISTER_TYPE_UW) {
1434            format(file, "0x%04xUW", imm_val);
1435         } else if (type == BRW_REGISTER_TYPE_HF) {
1436            format(file, "0x%04xHF", imm_val);
1437         }
1438         return 0;
1439      }
1440
1441      reg_nr = brw_inst_3src_src2_reg_nr(devinfo, inst);
1442      subreg_nr = brw_inst_3src_a1_src2_subreg_nr(devinfo, inst);
1443      type = brw_inst_3src_a1_src2_type(devinfo, inst);
1444      /* FINISHME: No vertical stride on src2. Is using the hstride in place
1445       *           correct? Doesn't seem like it, since there's hstride=1 but
1446       *           no vstride=1.
1447       */
1448      _vert_stride = vstride_from_align1_3src_hstride(
1449                        brw_inst_3src_a1_src2_hstride(devinfo, inst));
1450      _horiz_stride = hstride_from_align1_3src_hstride(
1451                         brw_inst_3src_a1_src2_hstride(devinfo, inst));
1452      _width = implied_width(_vert_stride, _horiz_stride);
1453   } else {
1454      _file = BRW_GENERAL_REGISTER_FILE;
1455      reg_nr = brw_inst_3src_src2_reg_nr(devinfo, inst);
1456      subreg_nr = brw_inst_3src_a16_src2_subreg_nr(devinfo, inst) * 4;
1457      type = brw_inst_3src_a16_src_type(devinfo, inst);
1458
1459      if (brw_inst_3src_a16_src2_rep_ctrl(devinfo, inst)) {
1460         _vert_stride = BRW_VERTICAL_STRIDE_0;
1461         _width = BRW_WIDTH_1;
1462         _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1463      } else {
1464         _vert_stride = BRW_VERTICAL_STRIDE_4;
1465         _width = BRW_WIDTH_4;
1466         _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1467      }
1468   }
1469   is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1470                      _width == BRW_WIDTH_1 &&
1471                      _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1472
1473   subreg_nr /= brw_reg_type_to_size(type);
1474
1475   err |= control(file, "negate", m_negate,
1476                  brw_inst_3src_src2_negate(devinfo, inst), NULL);
1477   err |= control(file, "abs", _abs, brw_inst_3src_src2_abs(devinfo, inst), NULL);
1478
1479   err |= reg(file, _file, reg_nr);
1480   if (err == -1)
1481      return 0;
1482   if (subreg_nr || is_scalar_region)
1483      format(file, ".%d", subreg_nr);
1484   src_align1_region(file, _vert_stride, _width, _horiz_stride);
1485   if (!is_scalar_region && !is_align1)
1486      err |= src_swizzle(file, brw_inst_3src_a16_src2_swizzle(devinfo, inst));
1487   string(file, brw_reg_type_to_letters(type));
1488   return err;
1489}
1490
1491static int
1492imm(FILE *file, const struct intel_device_info *devinfo, enum brw_reg_type type,
1493    const brw_inst *inst)
1494{
1495   switch (type) {
1496   case BRW_REGISTER_TYPE_UQ:
1497      format(file, "0x%016"PRIx64"UQ", brw_inst_imm_uq(devinfo, inst));
1498      break;
1499   case BRW_REGISTER_TYPE_Q:
1500      format(file, "0x%016"PRIx64"Q", brw_inst_imm_uq(devinfo, inst));
1501      break;
1502   case BRW_REGISTER_TYPE_UD:
1503      format(file, "0x%08xUD", brw_inst_imm_ud(devinfo, inst));
1504      break;
1505   case BRW_REGISTER_TYPE_D:
1506      format(file, "%dD", brw_inst_imm_d(devinfo, inst));
1507      break;
1508   case BRW_REGISTER_TYPE_UW:
1509      format(file, "0x%04xUW", (uint16_t) brw_inst_imm_ud(devinfo, inst));
1510      break;
1511   case BRW_REGISTER_TYPE_W:
1512      format(file, "%dW", (int16_t) brw_inst_imm_d(devinfo, inst));
1513      break;
1514   case BRW_REGISTER_TYPE_UV:
1515      format(file, "0x%08xUV", brw_inst_imm_ud(devinfo, inst));
1516      break;
1517   case BRW_REGISTER_TYPE_VF:
1518      format(file, "0x%"PRIx64"VF", brw_inst_bits(inst, 127, 96));
1519      pad(file, 48);
1520      format(file, "/* [%-gF, %-gF, %-gF, %-gF]VF */",
1521             brw_vf_to_float(brw_inst_imm_ud(devinfo, inst)),
1522             brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 8),
1523             brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 16),
1524             brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 24));
1525      break;
1526   case BRW_REGISTER_TYPE_V:
1527      format(file, "0x%08xV", brw_inst_imm_ud(devinfo, inst));
1528      break;
1529   case BRW_REGISTER_TYPE_F:
1530      /* The DIM instruction's src0 uses an F type but contains a
1531       * 64-bit immediate
1532       */
1533      if (brw_inst_opcode(devinfo, inst) == BRW_OPCODE_DIM) {
1534         format(file, "0x%"PRIx64"F", brw_inst_bits(inst, 127, 64));
1535         pad(file, 48);
1536         format(file, "/* %-gF */", brw_inst_imm_df(devinfo, inst));
1537      } else {
1538         format(file, "0x%"PRIx64"F", brw_inst_bits(inst, 127, 96));
1539         pad(file, 48);
1540         format(file, " /* %-gF */", brw_inst_imm_f(devinfo, inst));
1541      }
1542      break;
1543   case BRW_REGISTER_TYPE_DF:
1544      format(file, "0x%016"PRIx64"DF", brw_inst_bits(inst, 127, 64));
1545      pad(file, 48);
1546      format(file, "/* %-gDF */", brw_inst_imm_df(devinfo, inst));
1547      break;
1548   case BRW_REGISTER_TYPE_HF:
1549      string(file, "Half Float IMM");
1550      break;
1551   case BRW_REGISTER_TYPE_NF:
1552   case BRW_REGISTER_TYPE_UB:
1553   case BRW_REGISTER_TYPE_B:
1554      format(file, "*** invalid immediate type %d ", type);
1555   }
1556   return 0;
1557}
1558
1559static int
1560src_sends_da(FILE *file,
1561             const struct intel_device_info *devinfo,
1562             enum brw_reg_type type,
1563             enum brw_reg_file _reg_file,
1564             unsigned _reg_nr,
1565             unsigned _reg_subnr)
1566{
1567   int err = 0;
1568
1569   err |= reg(file, _reg_file, _reg_nr);
1570   if (err == -1)
1571      return 0;
1572   if (_reg_subnr)
1573      format(file, ".1");
1574   string(file, brw_reg_type_to_letters(type));
1575
1576   return err;
1577}
1578
1579static int
1580src_sends_ia(FILE *file,
1581             const struct intel_device_info *devinfo,
1582             enum brw_reg_type type,
1583             int _addr_imm,
1584             unsigned _addr_subreg_nr)
1585{
1586   string(file, "g[a0");
1587   if (_addr_subreg_nr)
1588      format(file, ".1");
1589   if (_addr_imm)
1590      format(file, " %d", _addr_imm);
1591   string(file, "]");
1592   string(file, brw_reg_type_to_letters(type));
1593
1594   return 0;
1595}
1596
1597static int
1598src_send_desc_ia(FILE *file,
1599                 const struct intel_device_info *devinfo,
1600                 unsigned _addr_subreg_nr)
1601{
1602   string(file, "a0");
1603   if (_addr_subreg_nr)
1604      format(file, ".%d", _addr_subreg_nr);
1605   format(file, "<0>UD");
1606
1607   return 0;
1608}
1609
1610static int
1611src0(FILE *file, const struct intel_device_info *devinfo, const brw_inst *inst)
1612{
1613   if (is_split_send(devinfo, brw_inst_opcode(devinfo, inst))) {
1614      if (devinfo->ver >= 12) {
1615         return src_sends_da(file,
1616                             devinfo,
1617                             BRW_REGISTER_TYPE_UD,
1618                             brw_inst_send_src0_reg_file(devinfo, inst),
1619                             brw_inst_src0_da_reg_nr(devinfo, inst),
1620                             0);
1621      } else if (brw_inst_send_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1622         return src_sends_da(file,
1623                             devinfo,
1624                             BRW_REGISTER_TYPE_UD,
1625                             BRW_GENERAL_REGISTER_FILE,
1626                             brw_inst_src0_da_reg_nr(devinfo, inst),
1627                             brw_inst_src0_da16_subreg_nr(devinfo, inst));
1628      } else {
1629         return src_sends_ia(file,
1630                             devinfo,
1631                             BRW_REGISTER_TYPE_UD,
1632                             brw_inst_send_src0_ia16_addr_imm(devinfo, inst),
1633                             brw_inst_src0_ia_subreg_nr(devinfo, inst));
1634      }
1635   } else if (brw_inst_src0_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE) {
1636      return imm(file, devinfo, brw_inst_src0_type(devinfo, inst), inst);
1637   } else if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1638      if (brw_inst_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1639         return src_da1(file,
1640                        devinfo,
1641                        brw_inst_opcode(devinfo, inst),
1642                        brw_inst_src0_type(devinfo, inst),
1643                        brw_inst_src0_reg_file(devinfo, inst),
1644                        brw_inst_src0_vstride(devinfo, inst),
1645                        brw_inst_src0_width(devinfo, inst),
1646                        brw_inst_src0_hstride(devinfo, inst),
1647                        brw_inst_src0_da_reg_nr(devinfo, inst),
1648                        brw_inst_src0_da1_subreg_nr(devinfo, inst),
1649                        brw_inst_src0_abs(devinfo, inst),
1650                        brw_inst_src0_negate(devinfo, inst));
1651      } else {
1652         return src_ia1(file,
1653                        devinfo,
1654                        brw_inst_opcode(devinfo, inst),
1655                        brw_inst_src0_type(devinfo, inst),
1656                        brw_inst_src0_ia1_addr_imm(devinfo, inst),
1657                        brw_inst_src0_ia_subreg_nr(devinfo, inst),
1658                        brw_inst_src0_negate(devinfo, inst),
1659                        brw_inst_src0_abs(devinfo, inst),
1660                        brw_inst_src0_hstride(devinfo, inst),
1661                        brw_inst_src0_width(devinfo, inst),
1662                        brw_inst_src0_vstride(devinfo, inst));
1663      }
1664   } else {
1665      if (brw_inst_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1666         return src_da16(file,
1667                         devinfo,
1668                         brw_inst_opcode(devinfo, inst),
1669                         brw_inst_src0_type(devinfo, inst),
1670                         brw_inst_src0_reg_file(devinfo, inst),
1671                         brw_inst_src0_vstride(devinfo, inst),
1672                         brw_inst_src0_da_reg_nr(devinfo, inst),
1673                         brw_inst_src0_da16_subreg_nr(devinfo, inst),
1674                         brw_inst_src0_abs(devinfo, inst),
1675                         brw_inst_src0_negate(devinfo, inst),
1676                         brw_inst_src0_da16_swiz_x(devinfo, inst),
1677                         brw_inst_src0_da16_swiz_y(devinfo, inst),
1678                         brw_inst_src0_da16_swiz_z(devinfo, inst),
1679                         brw_inst_src0_da16_swiz_w(devinfo, inst));
1680      } else {
1681         string(file, "Indirect align16 address mode not supported");
1682         return 1;
1683      }
1684   }
1685}
1686
1687static int
1688src1(FILE *file, const struct intel_device_info *devinfo, const brw_inst *inst)
1689{
1690   if (is_split_send(devinfo, brw_inst_opcode(devinfo, inst))) {
1691      return src_sends_da(file,
1692                          devinfo,
1693                          BRW_REGISTER_TYPE_UD,
1694                          brw_inst_send_src1_reg_file(devinfo, inst),
1695                          brw_inst_send_src1_reg_nr(devinfo, inst),
1696                          0 /* subreg_nr */);
1697   } else if (brw_inst_src1_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE) {
1698      return imm(file, devinfo, brw_inst_src1_type(devinfo, inst), inst);
1699   } else if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1700      if (brw_inst_src1_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1701         return src_da1(file,
1702                        devinfo,
1703                        brw_inst_opcode(devinfo, inst),
1704                        brw_inst_src1_type(devinfo, inst),
1705                        brw_inst_src1_reg_file(devinfo, inst),
1706                        brw_inst_src1_vstride(devinfo, inst),
1707                        brw_inst_src1_width(devinfo, inst),
1708                        brw_inst_src1_hstride(devinfo, inst),
1709                        brw_inst_src1_da_reg_nr(devinfo, inst),
1710                        brw_inst_src1_da1_subreg_nr(devinfo, inst),
1711                        brw_inst_src1_abs(devinfo, inst),
1712                        brw_inst_src1_negate(devinfo, inst));
1713      } else {
1714         return src_ia1(file,
1715                        devinfo,
1716                        brw_inst_opcode(devinfo, inst),
1717                        brw_inst_src1_type(devinfo, inst),
1718                        brw_inst_src1_ia1_addr_imm(devinfo, inst),
1719                        brw_inst_src1_ia_subreg_nr(devinfo, inst),
1720                        brw_inst_src1_negate(devinfo, inst),
1721                        brw_inst_src1_abs(devinfo, inst),
1722                        brw_inst_src1_hstride(devinfo, inst),
1723                        brw_inst_src1_width(devinfo, inst),
1724                        brw_inst_src1_vstride(devinfo, inst));
1725      }
1726   } else {
1727      if (brw_inst_src1_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1728         return src_da16(file,
1729                         devinfo,
1730                         brw_inst_opcode(devinfo, inst),
1731                         brw_inst_src1_type(devinfo, inst),
1732                         brw_inst_src1_reg_file(devinfo, inst),
1733                         brw_inst_src1_vstride(devinfo, inst),
1734                         brw_inst_src1_da_reg_nr(devinfo, inst),
1735                         brw_inst_src1_da16_subreg_nr(devinfo, inst),
1736                         brw_inst_src1_abs(devinfo, inst),
1737                         brw_inst_src1_negate(devinfo, inst),
1738                         brw_inst_src1_da16_swiz_x(devinfo, inst),
1739                         brw_inst_src1_da16_swiz_y(devinfo, inst),
1740                         brw_inst_src1_da16_swiz_z(devinfo, inst),
1741                         brw_inst_src1_da16_swiz_w(devinfo, inst));
1742      } else {
1743         string(file, "Indirect align16 address mode not supported");
1744         return 1;
1745      }
1746   }
1747}
1748
1749static int
1750qtr_ctrl(FILE *file, const struct intel_device_info *devinfo,
1751         const brw_inst *inst)
1752{
1753   int qtr_ctl = brw_inst_qtr_control(devinfo, inst);
1754   int exec_size = 1 << brw_inst_exec_size(devinfo, inst);
1755   const unsigned nib_ctl = devinfo->ver < 7 ? 0 :
1756                            brw_inst_nib_control(devinfo, inst);
1757
1758   if (exec_size < 8 || nib_ctl) {
1759      format(file, " %dN", qtr_ctl * 2 + nib_ctl + 1);
1760   } else if (exec_size == 8) {
1761      switch (qtr_ctl) {
1762      case 0:
1763         string(file, " 1Q");
1764         break;
1765      case 1:
1766         string(file, " 2Q");
1767         break;
1768      case 2:
1769         string(file, " 3Q");
1770         break;
1771      case 3:
1772         string(file, " 4Q");
1773         break;
1774      }
1775   } else if (exec_size == 16) {
1776      if (qtr_ctl < 2)
1777         string(file, " 1H");
1778      else
1779         string(file, " 2H");
1780   }
1781   return 0;
1782}
1783
1784static int
1785swsb(FILE *file, const struct intel_device_info *devinfo, const brw_inst *inst)
1786{
1787   const enum opcode opcode = brw_inst_opcode(devinfo, inst);
1788   const uint8_t x = brw_inst_swsb(devinfo, inst);
1789   const struct tgl_swsb swsb = tgl_swsb_decode(devinfo, opcode, x);
1790   if (swsb.regdist)
1791      format(file, " %s@%d",
1792             (swsb.pipe == TGL_PIPE_FLOAT ? "F" :
1793              swsb.pipe == TGL_PIPE_INT ? "I" :
1794              swsb.pipe == TGL_PIPE_LONG ? "L" :
1795              swsb.pipe == TGL_PIPE_ALL ? "A"  : "" ),
1796             swsb.regdist);
1797   if (swsb.mode)
1798      format(file, " $%d%s", swsb.sbid,
1799             (swsb.mode & TGL_SBID_SET ? "" :
1800              swsb.mode & TGL_SBID_DST ? ".dst" : ".src"));
1801   return 0;
1802}
1803
1804#ifdef DEBUG
1805static __attribute__((__unused__)) int
1806brw_disassemble_imm(const struct intel_device_info *devinfo,
1807                    uint32_t dw3, uint32_t dw2, uint32_t dw1, uint32_t dw0)
1808{
1809   brw_inst inst;
1810   inst.data[0] = (((uint64_t) dw1) << 32) | ((uint64_t) dw0);
1811   inst.data[1] = (((uint64_t) dw3) << 32) | ((uint64_t) dw2);
1812   return brw_disassemble_inst(stderr, devinfo, &inst, false, 0, NULL);
1813}
1814#endif
1815
1816static void
1817write_label(FILE *file, const struct intel_device_info *devinfo,
1818            const struct brw_label *root_label,
1819            int offset, int jump)
1820{
1821   if (root_label != NULL) {
1822      int to_bytes_scale = sizeof(brw_inst) / brw_jump_scale(devinfo);
1823      const struct brw_label *label =
1824         brw_find_label(root_label, offset + jump * to_bytes_scale);
1825      if (label != NULL) {
1826         format(file, " LABEL%d", label->number);
1827      }
1828   }
1829}
1830
1831static void
1832lsc_disassemble_ex_desc(const struct intel_device_info *devinfo,
1833                        uint32_t imm_desc,
1834                        uint32_t imm_ex_desc,
1835                        FILE *file)
1836{
1837   const unsigned addr_type = lsc_msg_desc_addr_type(devinfo, imm_desc);
1838   switch (addr_type) {
1839   case LSC_ADDR_SURFTYPE_FLAT:
1840      format(file, "base_offset %u ",
1841             lsc_flat_ex_desc_base_offset(devinfo, imm_ex_desc));
1842      break;
1843   case LSC_ADDR_SURFTYPE_BSS:
1844   case LSC_ADDR_SURFTYPE_SS:
1845      format(file, "surface_state_index %u ",
1846             lsc_bss_ex_desc_index(devinfo, imm_ex_desc));
1847      break;
1848   case LSC_ADDR_SURFTYPE_BTI:
1849      format(file, "BTI %u ",
1850             lsc_bti_ex_desc_index(devinfo, imm_ex_desc));
1851      format(file, "base_offset %u ",
1852             lsc_bti_ex_desc_base_offset(devinfo, imm_ex_desc));
1853      break;
1854   default:
1855      format(file, "unsupported address surface type %d", addr_type);
1856      break;
1857   }
1858}
1859
1860static inline bool
1861brw_sfid_is_lsc(unsigned sfid)
1862{
1863   switch (sfid) {
1864   case GFX12_SFID_UGM:
1865   case GFX12_SFID_SLM:
1866   case GFX12_SFID_TGM:
1867      return true;
1868   default:
1869      break;
1870   }
1871
1872   return false;
1873}
1874
1875int
1876brw_disassemble_inst(FILE *file, const struct intel_device_info *devinfo,
1877                     const brw_inst *inst, bool is_compacted,
1878                     int offset, const struct brw_label *root_label)
1879{
1880   int err = 0;
1881   int space = 0;
1882
1883   const enum opcode opcode = brw_inst_opcode(devinfo, inst);
1884   const struct opcode_desc *desc = brw_opcode_desc(devinfo, opcode);
1885
1886   if (brw_inst_pred_control(devinfo, inst)) {
1887      string(file, "(");
1888      err |= control(file, "predicate inverse", pred_inv,
1889                     brw_inst_pred_inv(devinfo, inst), NULL);
1890      format(file, "f%"PRIu64".%"PRIu64,
1891             devinfo->ver >= 7 ? brw_inst_flag_reg_nr(devinfo, inst) : 0,
1892             brw_inst_flag_subreg_nr(devinfo, inst));
1893      if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1894         err |= control(file, "predicate control align1", pred_ctrl_align1,
1895                        brw_inst_pred_control(devinfo, inst), NULL);
1896      } else {
1897         err |= control(file, "predicate control align16", pred_ctrl_align16,
1898                        brw_inst_pred_control(devinfo, inst), NULL);
1899      }
1900      string(file, ") ");
1901   }
1902
1903   err |= print_opcode(file, devinfo, opcode);
1904
1905   if (!is_send(opcode))
1906      err |= control(file, "saturate", saturate, brw_inst_saturate(devinfo, inst),
1907                     NULL);
1908
1909   err |= control(file, "debug control", debug_ctrl,
1910                  brw_inst_debug_control(devinfo, inst), NULL);
1911
1912   if (opcode == BRW_OPCODE_MATH) {
1913      string(file, " ");
1914      err |= control(file, "function", math_function,
1915                     brw_inst_math_function(devinfo, inst), NULL);
1916
1917   } else if (opcode == BRW_OPCODE_SYNC) {
1918      string(file, " ");
1919      err |= control(file, "function", sync_function,
1920                     brw_inst_cond_modifier(devinfo, inst), NULL);
1921
1922   } else if (!is_send(opcode)) {
1923      err |= control(file, "conditional modifier", conditional_modifier,
1924                     brw_inst_cond_modifier(devinfo, inst), NULL);
1925
1926      /* If we're using the conditional modifier, print which flags reg is
1927       * used for it.  Note that on gfx6+, the embedded-condition SEL and
1928       * control flow doesn't update flags.
1929       */
1930      if (brw_inst_cond_modifier(devinfo, inst) &&
1931          (devinfo->ver < 6 || (opcode != BRW_OPCODE_SEL &&
1932                                opcode != BRW_OPCODE_CSEL &&
1933                                opcode != BRW_OPCODE_IF &&
1934                                opcode != BRW_OPCODE_WHILE))) {
1935         format(file, ".f%"PRIu64".%"PRIu64,
1936                devinfo->ver >= 7 ? brw_inst_flag_reg_nr(devinfo, inst) : 0,
1937                brw_inst_flag_subreg_nr(devinfo, inst));
1938      }
1939   }
1940
1941   if (opcode != BRW_OPCODE_NOP && opcode != BRW_OPCODE_NENOP) {
1942      string(file, "(");
1943      err |= control(file, "execution size", exec_size,
1944                     brw_inst_exec_size(devinfo, inst), NULL);
1945      string(file, ")");
1946   }
1947
1948   if (opcode == BRW_OPCODE_SEND && devinfo->ver < 6)
1949      format(file, " %"PRIu64, brw_inst_base_mrf(devinfo, inst));
1950
1951   if (brw_has_uip(devinfo, opcode)) {
1952      /* Instructions that have UIP also have JIP. */
1953      pad(file, 16);
1954      string(file, "JIP: ");
1955      write_label(file, devinfo, root_label, offset, brw_inst_jip(devinfo, inst));
1956
1957      pad(file, 38);
1958      string(file, "UIP: ");
1959      write_label(file, devinfo, root_label, offset, brw_inst_uip(devinfo, inst));
1960   } else if (brw_has_jip(devinfo, opcode)) {
1961      int jip;
1962      if (devinfo->ver >= 7) {
1963         jip = brw_inst_jip(devinfo, inst);
1964      } else {
1965         jip = brw_inst_gfx6_jump_count(devinfo, inst);
1966      }
1967
1968      pad(file, 16);
1969      string(file, "JIP: ");
1970      write_label(file, devinfo, root_label, offset, jip);
1971   } else if (devinfo->ver < 6 && (opcode == BRW_OPCODE_BREAK ||
1972                                   opcode == BRW_OPCODE_CONTINUE ||
1973                                   opcode == BRW_OPCODE_ELSE)) {
1974      pad(file, 16);
1975      format(file, "Jump: %d", brw_inst_gfx4_jump_count(devinfo, inst));
1976      pad(file, 32);
1977      format(file, "Pop: %"PRIu64, brw_inst_gfx4_pop_count(devinfo, inst));
1978   } else if (devinfo->ver < 6 && (opcode == BRW_OPCODE_IF ||
1979                                   opcode == BRW_OPCODE_IFF ||
1980                                   opcode == BRW_OPCODE_HALT ||
1981                                   opcode == BRW_OPCODE_WHILE)) {
1982      pad(file, 16);
1983      format(file, "Jump: %d", brw_inst_gfx4_jump_count(devinfo, inst));
1984   } else if (devinfo->ver < 6 && opcode == BRW_OPCODE_ENDIF) {
1985      pad(file, 16);
1986      format(file, "Pop: %"PRIu64, brw_inst_gfx4_pop_count(devinfo, inst));
1987   } else if (opcode == BRW_OPCODE_JMPI) {
1988      pad(file, 16);
1989      err |= src1(file, devinfo, inst);
1990   } else if (desc && desc->nsrc == 3) {
1991      pad(file, 16);
1992      err |= dest_3src(file, devinfo, inst);
1993
1994      pad(file, 32);
1995      err |= src0_3src(file, devinfo, inst);
1996
1997      pad(file, 48);
1998      err |= src1_3src(file, devinfo, inst);
1999
2000      pad(file, 64);
2001      err |= src2_3src(file, devinfo, inst);
2002   } else if (desc) {
2003      if (desc->ndst > 0) {
2004         pad(file, 16);
2005         err |= dest(file, devinfo, inst);
2006      }
2007
2008      if (desc->nsrc > 0) {
2009         pad(file, 32);
2010         err |= src0(file, devinfo, inst);
2011      }
2012
2013      if (desc->nsrc > 1) {
2014         pad(file, 48);
2015         err |= src1(file, devinfo, inst);
2016      }
2017   }
2018
2019   if (is_send(opcode)) {
2020      enum brw_message_target sfid = brw_inst_sfid(devinfo, inst);
2021
2022      bool has_imm_desc = false, has_imm_ex_desc = false;
2023      uint32_t imm_desc = 0, imm_ex_desc = 0;
2024      if (is_split_send(devinfo, opcode)) {
2025         pad(file, 64);
2026         if (brw_inst_send_sel_reg32_desc(devinfo, inst)) {
2027            /* show the indirect descriptor source */
2028            err |= src_send_desc_ia(file, devinfo, 0);
2029         } else {
2030            has_imm_desc = true;
2031            imm_desc = brw_inst_send_desc(devinfo, inst);
2032            fprintf(file, "0x%08"PRIx32, imm_desc);
2033         }
2034
2035         pad(file, 80);
2036         if (brw_inst_send_sel_reg32_ex_desc(devinfo, inst)) {
2037            /* show the indirect descriptor source */
2038            err |= src_send_desc_ia(file, devinfo,
2039                                    brw_inst_send_ex_desc_ia_subreg_nr(devinfo, inst));
2040         } else {
2041            has_imm_ex_desc = true;
2042            imm_ex_desc = brw_inst_sends_ex_desc(devinfo, inst);
2043            fprintf(file, "0x%08"PRIx32, imm_ex_desc);
2044         }
2045      } else {
2046         if (brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
2047            /* show the indirect descriptor source */
2048            pad(file, 48);
2049            err |= src1(file, devinfo, inst);
2050            pad(file, 64);
2051         } else {
2052            has_imm_desc = true;
2053            imm_desc = brw_inst_send_desc(devinfo, inst);
2054            pad(file, 48);
2055         }
2056
2057         /* Print message descriptor as immediate source */
2058         fprintf(file, "0x%08"PRIx64, inst->data[1] >> 32);
2059      }
2060
2061      newline(file);
2062      pad(file, 16);
2063      space = 0;
2064
2065      fprintf(file, "            ");
2066      err |= control(file, "SFID", devinfo->ver >= 6 ? gfx6_sfid : gfx4_sfid,
2067                     sfid, &space);
2068      string(file, " MsgDesc:");
2069
2070      if (!has_imm_desc) {
2071         format(file, " indirect");
2072      } else {
2073         bool unsupported = false;
2074         switch (sfid) {
2075         case BRW_SFID_MATH:
2076            err |= control(file, "math function", math_function,
2077                           brw_inst_math_msg_function(devinfo, inst), &space);
2078            err |= control(file, "math saturate", math_saturate,
2079                           brw_inst_math_msg_saturate(devinfo, inst), &space);
2080            err |= control(file, "math signed", math_signed,
2081                           brw_inst_math_msg_signed_int(devinfo, inst), &space);
2082            err |= control(file, "math scalar", math_scalar,
2083                           brw_inst_math_msg_data_type(devinfo, inst), &space);
2084            err |= control(file, "math precision", math_precision,
2085                           brw_inst_math_msg_precision(devinfo, inst), &space);
2086            break;
2087         case BRW_SFID_SAMPLER:
2088            if (devinfo->ver >= 5) {
2089               err |= control(file, "sampler message", gfx5_sampler_msg_type,
2090                              brw_sampler_desc_msg_type(devinfo, imm_desc),
2091                              &space);
2092               err |= control(file, "sampler simd mode", gfx5_sampler_simd_mode,
2093                              brw_sampler_desc_simd_mode(devinfo, imm_desc),
2094                              &space);
2095               format(file, " Surface = %u Sampler = %u",
2096                      brw_sampler_desc_binding_table_index(devinfo, imm_desc),
2097                      brw_sampler_desc_sampler(devinfo, imm_desc));
2098            } else {
2099               format(file, " (bti %u, sampler %u, msg_type %u, ",
2100                      brw_sampler_desc_binding_table_index(devinfo, imm_desc),
2101                      brw_sampler_desc_sampler(devinfo, imm_desc),
2102                      brw_sampler_desc_msg_type(devinfo, imm_desc));
2103               if (!devinfo->is_g4x) {
2104                  err |= control(file, "sampler target format",
2105                                 sampler_target_format,
2106                                 brw_sampler_desc_return_format(devinfo, imm_desc),
2107                                 NULL);
2108               }
2109               string(file, ")");
2110            }
2111            break;
2112         case GFX6_SFID_DATAPORT_SAMPLER_CACHE:
2113         case GFX6_SFID_DATAPORT_CONSTANT_CACHE:
2114            /* aka BRW_SFID_DATAPORT_READ on Gfx4-5 */
2115            if (devinfo->ver >= 6) {
2116               format(file, " (bti %u, msg_ctrl %u, msg_type %u, write_commit %u)",
2117                      brw_dp_desc_binding_table_index(devinfo, imm_desc),
2118                      brw_dp_desc_msg_control(devinfo, imm_desc),
2119                      brw_dp_desc_msg_type(devinfo, imm_desc),
2120                      devinfo->ver >= 7 ? 0u :
2121                      brw_dp_write_desc_write_commit(devinfo, imm_desc));
2122            } else {
2123               bool is_965 = devinfo->ver == 4 && !devinfo->is_g4x;
2124               err |= control(file, "DP read message type",
2125                              is_965 ? gfx4_dp_read_port_msg_type :
2126                                       g45_dp_read_port_msg_type,
2127                              brw_dp_read_desc_msg_type(devinfo, imm_desc),
2128                              &space);
2129
2130               format(file, " MsgCtrl = 0x%u",
2131                      brw_dp_read_desc_msg_control(devinfo, imm_desc));
2132
2133               format(file, " Surface = %u",
2134                      brw_dp_desc_binding_table_index(devinfo, imm_desc));
2135            }
2136            break;
2137
2138         case GFX6_SFID_DATAPORT_RENDER_CACHE: {
2139            /* aka BRW_SFID_DATAPORT_WRITE on Gfx4-5 */
2140            unsigned msg_type = brw_fb_write_desc_msg_type(devinfo, imm_desc);
2141
2142            err |= control(file, "DP rc message type",
2143                           dp_rc_msg_type(devinfo), msg_type, &space);
2144
2145            bool is_rt_write = msg_type ==
2146               (devinfo->ver >= 6 ? GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE
2147                                  : BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE);
2148
2149            if (is_rt_write) {
2150               err |= control(file, "RT message type", m_rt_write_subtype,
2151                              brw_inst_rt_message_type(devinfo, inst), &space);
2152               if (devinfo->ver >= 6 && brw_inst_rt_slot_group(devinfo, inst))
2153                  string(file, " Hi");
2154               if (brw_fb_write_desc_last_render_target(devinfo, imm_desc))
2155                  string(file, " LastRT");
2156               if (devinfo->ver >= 10 &&
2157                   brw_fb_write_desc_coarse_write(devinfo, imm_desc))
2158                  string(file, " CoarseWrite");
2159               if (devinfo->ver < 7 &&
2160                   brw_fb_write_desc_write_commit(devinfo, imm_desc))
2161                  string(file, " WriteCommit");
2162            } else {
2163               format(file, " MsgCtrl = 0x%u",
2164                      brw_fb_write_desc_msg_control(devinfo, imm_desc));
2165            }
2166
2167            format(file, " Surface = %u",
2168                   brw_fb_desc_binding_table_index(devinfo, imm_desc));
2169            break;
2170         }
2171
2172         case BRW_SFID_URB: {
2173            unsigned opcode = brw_inst_urb_opcode(devinfo, inst);
2174
2175            format(file, " offset %"PRIu64, brw_inst_urb_global_offset(devinfo, inst));
2176
2177            space = 1;
2178
2179            err |= control(file, "urb opcode",
2180                           devinfo->ver >= 7 ? gfx7_urb_opcode
2181                                             : gfx5_urb_opcode,
2182                           opcode, &space);
2183
2184            if (devinfo->ver >= 7 &&
2185                brw_inst_urb_per_slot_offset(devinfo, inst)) {
2186               string(file, " per-slot");
2187            }
2188
2189            if (opcode == GFX8_URB_OPCODE_SIMD8_WRITE ||
2190                opcode == GFX8_URB_OPCODE_SIMD8_READ) {
2191               if (brw_inst_urb_channel_mask_present(devinfo, inst))
2192                  string(file, " masked");
2193            } else if (opcode != GFX125_URB_OPCODE_FENCE) {
2194               err |= control(file, "urb swizzle", urb_swizzle,
2195                              brw_inst_urb_swizzle_control(devinfo, inst),
2196                              &space);
2197            }
2198
2199            if (devinfo->ver < 7) {
2200               err |= control(file, "urb allocate", urb_allocate,
2201                              brw_inst_urb_allocate(devinfo, inst), &space);
2202               err |= control(file, "urb used", urb_used,
2203                              brw_inst_urb_used(devinfo, inst), &space);
2204            }
2205            if (devinfo->ver < 8) {
2206               err |= control(file, "urb complete", urb_complete,
2207                              brw_inst_urb_complete(devinfo, inst), &space);
2208            }
2209            break;
2210         }
2211         case BRW_SFID_THREAD_SPAWNER:
2212            break;
2213
2214         case BRW_SFID_MESSAGE_GATEWAY:
2215            format(file, " (%s)",
2216                   gfx7_gateway_subfuncid[brw_inst_gateway_subfuncid(devinfo, inst)]);
2217            break;
2218
2219         case GFX12_SFID_SLM:
2220         case GFX12_SFID_TGM:
2221         case GFX12_SFID_UGM: {
2222            assert(devinfo->has_lsc);
2223            format(file, " (");
2224            const enum lsc_opcode op = lsc_msg_desc_opcode(devinfo, imm_desc);
2225            err |= control(file, "operation", lsc_operation,
2226                           op, &space);
2227            format(file, ",");
2228            err |= control(file, "addr_size", lsc_addr_size,
2229                           lsc_msg_desc_addr_size(devinfo, imm_desc),
2230                           &space);
2231
2232            if (op == LSC_OP_FENCE) {
2233               format(file, ",");
2234               err |= control(file, "scope", lsc_fence_scope,
2235                              lsc_fence_msg_desc_scope(devinfo, imm_desc),
2236                              &space);
2237               format(file, ",");
2238               err |= control(file, "flush_type", lsc_flush_type,
2239                              lsc_fence_msg_desc_flush_type(devinfo, imm_desc),
2240                              &space);
2241               format(file, ",");
2242               err |= control(file, "backup_mode_fence_routing",
2243                              lsc_backup_fence_routing,
2244                              lsc_fence_msg_desc_backup_routing(devinfo, imm_desc),
2245                              &space);
2246            } else {
2247               format(file, ",");
2248               err |= control(file, "data_size", lsc_data_size,
2249                              lsc_msg_desc_data_size(devinfo, imm_desc),
2250                              &space);
2251               format(file, ",");
2252               if (lsc_opcode_has_cmask(op)) {
2253                  err |= control(file, "component_mask",
2254                                 lsc_cmask_str,
2255                                 lsc_msg_desc_cmask(devinfo, imm_desc),
2256                                 &space);
2257               } else {
2258                  err |= control(file, "vector_size",
2259                                 lsc_vect_size_str,
2260                                 lsc_msg_desc_vect_size(devinfo, imm_desc),
2261                                 &space);
2262                  if (lsc_msg_desc_transpose(devinfo, imm_desc))
2263                     format(file, ", transpose");
2264               }
2265               switch(op) {
2266               case LSC_OP_LOAD_CMASK:
2267               case LSC_OP_LOAD:
2268                  format(file, ",");
2269                  err |= control(file, "cache_load",
2270                                 lsc_cache_load,
2271                                 lsc_msg_desc_cache_ctrl(devinfo, imm_desc),
2272                                 &space);
2273                  break;
2274               default:
2275                  format(file, ",");
2276                  err |= control(file, "cache_store",
2277                                 lsc_cache_store,
2278                                 lsc_msg_desc_cache_ctrl(devinfo, imm_desc),
2279                                 &space);
2280                  break;
2281               }
2282            }
2283            format(file, " dst_len = %u,", lsc_msg_desc_dest_len(devinfo, imm_desc));
2284            format(file, " src0_len = %u,", lsc_msg_desc_src0_len(devinfo, imm_desc));
2285            format(file, " src1_len = %d", brw_message_ex_desc_ex_mlen(devinfo, imm_ex_desc));
2286            err |= control(file, "address_type", lsc_addr_surface_type,
2287                           lsc_msg_desc_addr_type(devinfo, imm_desc), &space);
2288            format(file, " )");
2289            break;
2290         }
2291
2292         case GFX7_SFID_DATAPORT_DATA_CACHE:
2293            if (devinfo->ver >= 7) {
2294               format(file, " (");
2295               space = 0;
2296
2297               err |= control(file, "DP DC0 message type",
2298                              dp_dc0_msg_type_gfx7,
2299                              brw_dp_desc_msg_type(devinfo, imm_desc), &space);
2300
2301               format(file, ", bti %u, ",
2302                      brw_dp_desc_binding_table_index(devinfo, imm_desc));
2303
2304               switch (brw_inst_dp_msg_type(devinfo, inst)) {
2305               case GFX7_DATAPORT_DC_UNTYPED_ATOMIC_OP:
2306                  control(file, "atomic op", aop,
2307                          brw_dp_desc_msg_control(devinfo, imm_desc) & 0xf,
2308                          &space);
2309                  break;
2310               case GFX7_DATAPORT_DC_OWORD_BLOCK_READ:
2311               case GFX7_DATAPORT_DC_OWORD_BLOCK_WRITE: {
2312                  unsigned msg_ctrl = brw_dp_desc_msg_control(devinfo, imm_desc);
2313                  assert(dp_oword_block_rw[msg_ctrl & 7]);
2314                  format(file, "owords = %s, aligned = %d",
2315                        dp_oword_block_rw[msg_ctrl & 7], (msg_ctrl >> 3) & 3);
2316                  break;
2317               }
2318               default:
2319                  format(file, "%u",
2320                         brw_dp_desc_msg_control(devinfo, imm_desc));
2321               }
2322               format(file, ")");
2323            } else {
2324               unsupported = true;
2325            }
2326            break;
2327
2328         case HSW_SFID_DATAPORT_DATA_CACHE_1: {
2329            if (devinfo->ver >= 7) {
2330               format(file, " (");
2331               space = 0;
2332
2333               unsigned msg_ctrl = brw_dp_desc_msg_control(devinfo, imm_desc);
2334
2335               err |= control(file, "DP DC1 message type",
2336                              dp_dc1_msg_type_hsw,
2337                              brw_dp_desc_msg_type(devinfo, imm_desc), &space);
2338
2339               format(file, ", Surface = %u, ",
2340                      brw_dp_desc_binding_table_index(devinfo, imm_desc));
2341
2342               switch (brw_inst_dp_msg_type(devinfo, inst)) {
2343               case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP:
2344               case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP:
2345               case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP:
2346                  format(file, "SIMD%d,", (msg_ctrl & (1 << 4)) ? 8 : 16);
2347                  FALLTHROUGH;
2348               case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2:
2349               case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2:
2350               case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2:
2351               case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_OP:
2352               case GFX12_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_HALF_INT_OP:
2353                  control(file, "atomic op", aop, msg_ctrl & 0xf, &space);
2354                  break;
2355               case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ:
2356               case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE:
2357               case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ:
2358               case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE:
2359               case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_WRITE:
2360               case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_READ: {
2361                  static const char *simd_modes[] = { "4x2", "16", "8" };
2362                  format(file, "SIMD%s, Mask = 0x%x",
2363                         simd_modes[msg_ctrl >> 4], msg_ctrl & 0xf);
2364                  break;
2365               }
2366               case GFX9_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_FLOAT_OP:
2367               case GFX9_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_FLOAT_OP:
2368               case GFX12_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_HALF_FLOAT_OP:
2369                  format(file, "SIMD%d,", (msg_ctrl & (1 << 4)) ? 8 : 16);
2370                  control(file, "atomic float op", aop_float, msg_ctrl & 0xf,
2371                          &space);
2372                  break;
2373               case GFX9_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_WRITE:
2374               case GFX9_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_READ:
2375                  assert(dp_oword_block_rw[msg_ctrl & 7]);
2376                  format(file, "owords = %s, aligned = %d",
2377                        dp_oword_block_rw[msg_ctrl & 7], (msg_ctrl >> 3) & 3);
2378                  break;
2379               default:
2380                  format(file, "0x%x", msg_ctrl);
2381               }
2382               format(file, ")");
2383            } else {
2384               unsupported = true;
2385            }
2386            break;
2387         }
2388
2389         case GFX7_SFID_PIXEL_INTERPOLATOR:
2390            if (devinfo->ver >= 7) {
2391               format(file, " (%s, %s, 0x%02"PRIx64")",
2392                      brw_inst_pi_nopersp(devinfo, inst) ? "linear" : "persp",
2393                      pixel_interpolator_msg_types[brw_inst_pi_message_type(devinfo, inst)],
2394                      brw_inst_pi_message_data(devinfo, inst));
2395            } else {
2396               unsupported = true;
2397            }
2398            break;
2399
2400         case GEN_RT_SFID_RAY_TRACE_ACCELERATOR:
2401            if (devinfo->has_ray_tracing) {
2402               format(file, " SIMD%d,",
2403                      brw_rt_trace_ray_desc_exec_size(devinfo, imm_desc));
2404            } else {
2405               unsupported = true;
2406            }
2407            break;
2408
2409         default:
2410            unsupported = true;
2411            break;
2412         }
2413
2414         if (unsupported)
2415            format(file, "unsupported shared function ID %d", sfid);
2416
2417         if (space)
2418            string(file, " ");
2419      }
2420      if (brw_sfid_is_lsc(sfid)) {
2421            lsc_disassemble_ex_desc(devinfo, imm_desc, imm_ex_desc, file);
2422      } else {
2423         if (has_imm_desc)
2424            format(file, "mlen %u", brw_message_desc_mlen(devinfo, imm_desc));
2425         if (has_imm_ex_desc) {
2426            format(file, " ex_mlen %u",
2427                   brw_message_ex_desc_ex_mlen(devinfo, imm_ex_desc));
2428         }
2429         if (has_imm_desc)
2430            format(file, " rlen %u", brw_message_desc_rlen(devinfo, imm_desc));
2431      }
2432   }
2433   pad(file, 64);
2434   if (opcode != BRW_OPCODE_NOP && opcode != BRW_OPCODE_NENOP) {
2435      string(file, "{");
2436      space = 1;
2437      err |= control(file, "access mode", access_mode,
2438                     brw_inst_access_mode(devinfo, inst), &space);
2439      if (devinfo->ver >= 6) {
2440         err |= control(file, "write enable control", wectrl,
2441                        brw_inst_mask_control(devinfo, inst), &space);
2442      } else {
2443         err |= control(file, "mask control", mask_ctrl,
2444                        brw_inst_mask_control(devinfo, inst), &space);
2445      }
2446
2447      if (devinfo->ver < 12) {
2448         err |= control(file, "dependency control", dep_ctrl,
2449                        ((brw_inst_no_dd_check(devinfo, inst) << 1) |
2450                         brw_inst_no_dd_clear(devinfo, inst)), &space);
2451      }
2452
2453      if (devinfo->ver >= 6)
2454         err |= qtr_ctrl(file, devinfo, inst);
2455      else {
2456         if (brw_inst_qtr_control(devinfo, inst) == BRW_COMPRESSION_COMPRESSED &&
2457             desc && desc->ndst > 0 &&
2458             brw_inst_dst_reg_file(devinfo, inst) == BRW_MESSAGE_REGISTER_FILE &&
2459             brw_inst_dst_da_reg_nr(devinfo, inst) & BRW_MRF_COMPR4) {
2460            format(file, " compr4");
2461         } else {
2462            err |= control(file, "compression control", compr_ctrl,
2463                           brw_inst_qtr_control(devinfo, inst), &space);
2464         }
2465      }
2466
2467      if (devinfo->ver >= 12)
2468         err |= swsb(file, devinfo, inst);
2469
2470      err |= control(file, "compaction", cmpt_ctrl, is_compacted, &space);
2471      err |= control(file, "thread control", thread_ctrl,
2472                     (devinfo->ver >= 12 ? brw_inst_atomic_control(devinfo, inst) :
2473                                           brw_inst_thread_control(devinfo, inst)),
2474                     &space);
2475      if (has_branch_ctrl(devinfo, opcode)) {
2476         err |= control(file, "branch ctrl", branch_ctrl,
2477                        brw_inst_branch_control(devinfo, inst), &space);
2478      } else if (devinfo->ver >= 6) {
2479         err |= control(file, "acc write control", accwr,
2480                        brw_inst_acc_wr_control(devinfo, inst), &space);
2481      }
2482      if (is_send(opcode))
2483         err |= control(file, "end of thread", end_of_thread,
2484                        brw_inst_eot(devinfo, inst), &space);
2485      if (space)
2486         string(file, " ");
2487      string(file, "}");
2488   }
2489   string(file, ";");
2490   newline(file);
2491   return err;
2492}
2493