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