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 <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "elk_disasm.h"
30 #include "elk_disasm_info.h"
31 #include "elk_eu_defines.h"
32 #include "elk_eu.h"
33 #include "elk_inst.h"
34 #include "elk_isa_info.h"
35 #include "elk_reg.h"
36 #include "elk_shader.h"
37 #include "util/half_float.h"
38
39 bool
elk_has_jip(const struct intel_device_info * devinfo,enum elk_opcode opcode)40 elk_has_jip(const struct intel_device_info *devinfo, enum elk_opcode opcode)
41 {
42 if (devinfo->ver < 6)
43 return false;
44
45 return opcode == ELK_OPCODE_IF ||
46 opcode == ELK_OPCODE_ELSE ||
47 opcode == ELK_OPCODE_ENDIF ||
48 opcode == ELK_OPCODE_WHILE ||
49 opcode == ELK_OPCODE_BREAK ||
50 opcode == ELK_OPCODE_CONTINUE ||
51 opcode == ELK_OPCODE_HALT;
52 }
53
54 bool
elk_has_uip(const struct intel_device_info * devinfo,enum elk_opcode opcode)55 elk_has_uip(const struct intel_device_info *devinfo, enum elk_opcode opcode)
56 {
57 if (devinfo->ver < 6)
58 return false;
59
60 return (devinfo->ver >= 7 && opcode == ELK_OPCODE_IF) ||
61 (devinfo->ver >= 8 && opcode == ELK_OPCODE_ELSE) ||
62 opcode == ELK_OPCODE_BREAK ||
63 opcode == ELK_OPCODE_CONTINUE ||
64 opcode == ELK_OPCODE_HALT;
65 }
66
67 static bool
has_branch_ctrl(const struct intel_device_info * devinfo,enum elk_opcode opcode)68 has_branch_ctrl(const struct intel_device_info *devinfo, enum elk_opcode opcode)
69 {
70 if (devinfo->ver < 8)
71 return false;
72
73 return opcode == ELK_OPCODE_IF ||
74 opcode == ELK_OPCODE_ELSE;
75 /* opcode == ELK_OPCODE_GOTO; */
76 }
77
78 static bool
is_logic_instruction(unsigned opcode)79 is_logic_instruction(unsigned opcode)
80 {
81 return opcode == ELK_OPCODE_AND ||
82 opcode == ELK_OPCODE_NOT ||
83 opcode == ELK_OPCODE_OR ||
84 opcode == ELK_OPCODE_XOR;
85 }
86
87 static bool
is_send(unsigned opcode)88 is_send(unsigned opcode)
89 {
90 return opcode == ELK_OPCODE_SEND ||
91 opcode == ELK_OPCODE_SENDC;
92 }
93
94 const char *const elk_conditional_modifier[16] = {
95 [ELK_CONDITIONAL_NONE] = "",
96 [ELK_CONDITIONAL_Z] = ".z",
97 [ELK_CONDITIONAL_NZ] = ".nz",
98 [ELK_CONDITIONAL_G] = ".g",
99 [ELK_CONDITIONAL_GE] = ".ge",
100 [ELK_CONDITIONAL_L] = ".l",
101 [ELK_CONDITIONAL_LE] = ".le",
102 [ELK_CONDITIONAL_R] = ".r",
103 [ELK_CONDITIONAL_O] = ".o",
104 [ELK_CONDITIONAL_U] = ".u",
105 };
106
107 static const char *const m_negate[2] = {
108 [0] = "",
109 [1] = "-",
110 };
111
112 static const char *const _abs[2] = {
113 [0] = "",
114 [1] = "(abs)",
115 };
116
117 static const char *const m_bitnot[2] = { "", "~" };
118
119 static const char *const vert_stride[16] = {
120 [0] = "0",
121 [1] = "1",
122 [2] = "2",
123 [3] = "4",
124 [4] = "8",
125 [5] = "16",
126 [6] = "32",
127 [15] = "VxH",
128 };
129
130 static const char *const width[8] = {
131 [0] = "1",
132 [1] = "2",
133 [2] = "4",
134 [3] = "8",
135 [4] = "16",
136 };
137
138 static const char *const horiz_stride[4] = {
139 [0] = "0",
140 [1] = "1",
141 [2] = "2",
142 [3] = "4"
143 };
144
145 static const char *const chan_sel[4] = {
146 [0] = "x",
147 [1] = "y",
148 [2] = "z",
149 [3] = "w",
150 };
151
152 static const char *const debug_ctrl[2] = {
153 [0] = "",
154 [1] = ".breakpoint"
155 };
156
157 static const char *const saturate[2] = {
158 [0] = "",
159 [1] = ".sat"
160 };
161
162 static const char *const cmpt_ctrl[2] = {
163 [0] = "",
164 [1] = "compacted"
165 };
166
167 static const char *const accwr[2] = {
168 [0] = "",
169 [1] = "AccWrEnable"
170 };
171
172 static const char *const branch_ctrl[2] = {
173 [0] = "",
174 [1] = "BranchCtrl"
175 };
176
177 static const char *const wectrl[2] = {
178 [0] = "",
179 [1] = "WE_all"
180 };
181
182 static const char *const exec_size[8] = {
183 [0] = "1",
184 [1] = "2",
185 [2] = "4",
186 [3] = "8",
187 [4] = "16",
188 [5] = "32"
189 };
190
191 static const char *const pred_inv[2] = {
192 [0] = "+",
193 [1] = "-"
194 };
195
196 const char *const elk_pred_ctrl_align16[16] = {
197 [1] = "",
198 [2] = ".x",
199 [3] = ".y",
200 [4] = ".z",
201 [5] = ".w",
202 [6] = ".any4h",
203 [7] = ".all4h",
204 };
205
206 static const char *const pred_ctrl_align1[16] = {
207 [ELK_PREDICATE_NORMAL] = "",
208 [ELK_PREDICATE_ALIGN1_ANYV] = ".anyv",
209 [ELK_PREDICATE_ALIGN1_ALLV] = ".allv",
210 [ELK_PREDICATE_ALIGN1_ANY2H] = ".any2h",
211 [ELK_PREDICATE_ALIGN1_ALL2H] = ".all2h",
212 [ELK_PREDICATE_ALIGN1_ANY4H] = ".any4h",
213 [ELK_PREDICATE_ALIGN1_ALL4H] = ".all4h",
214 [ELK_PREDICATE_ALIGN1_ANY8H] = ".any8h",
215 [ELK_PREDICATE_ALIGN1_ALL8H] = ".all8h",
216 [ELK_PREDICATE_ALIGN1_ANY16H] = ".any16h",
217 [ELK_PREDICATE_ALIGN1_ALL16H] = ".all16h",
218 [ELK_PREDICATE_ALIGN1_ANY32H] = ".any32h",
219 [ELK_PREDICATE_ALIGN1_ALL32H] = ".all32h",
220 };
221
222 static const char *const thread_ctrl[4] = {
223 [ELK_THREAD_NORMAL] = "",
224 [ELK_THREAD_ATOMIC] = "atomic",
225 [ELK_THREAD_SWITCH] = "switch",
226 };
227
228 static const char *const compr_ctrl[4] = {
229 [0] = "",
230 [1] = "sechalf",
231 [2] = "compr",
232 [3] = "compr4",
233 };
234
235 static const char *const dep_ctrl[4] = {
236 [0] = "",
237 [1] = "NoDDClr",
238 [2] = "NoDDChk",
239 [3] = "NoDDClr,NoDDChk",
240 };
241
242 static const char *const mask_ctrl[4] = {
243 [0] = "",
244 [1] = "nomask",
245 };
246
247 static const char *const access_mode[2] = {
248 [0] = "align1",
249 [1] = "align16",
250 };
251
252 static const char *const reg_file[4] = {
253 [0] = "A",
254 [1] = "g",
255 [2] = "m",
256 [3] = "imm",
257 };
258
259 static const char *const writemask[16] = {
260 [0x0] = ".",
261 [0x1] = ".x",
262 [0x2] = ".y",
263 [0x3] = ".xy",
264 [0x4] = ".z",
265 [0x5] = ".xz",
266 [0x6] = ".yz",
267 [0x7] = ".xyz",
268 [0x8] = ".w",
269 [0x9] = ".xw",
270 [0xa] = ".yw",
271 [0xb] = ".xyw",
272 [0xc] = ".zw",
273 [0xd] = ".xzw",
274 [0xe] = ".yzw",
275 [0xf] = "",
276 };
277
278 static const char *const end_of_thread[2] = {
279 [0] = "",
280 [1] = "EOT"
281 };
282
283 /* SFIDs on Gfx4-5 */
284 static const char *const gfx4_sfid[16] = {
285 [ELK_SFID_NULL] = "null",
286 [ELK_SFID_MATH] = "math",
287 [ELK_SFID_SAMPLER] = "sampler",
288 [ELK_SFID_MESSAGE_GATEWAY] = "gateway",
289 [ELK_SFID_DATAPORT_READ] = "read",
290 [ELK_SFID_DATAPORT_WRITE] = "write",
291 [ELK_SFID_URB] = "urb",
292 [ELK_SFID_THREAD_SPAWNER] = "thread_spawner",
293 [ELK_SFID_VME] = "vme",
294 };
295
296 static const char *const gfx6_sfid[16] = {
297 [ELK_SFID_NULL] = "null",
298 [ELK_SFID_MATH] = "math",
299 [ELK_SFID_SAMPLER] = "sampler",
300 [ELK_SFID_MESSAGE_GATEWAY] = "gateway",
301 [ELK_SFID_URB] = "urb",
302 [ELK_SFID_THREAD_SPAWNER] = "thread_spawner",
303 [GFX6_SFID_DATAPORT_SAMPLER_CACHE] = "dp_sampler",
304 [GFX6_SFID_DATAPORT_RENDER_CACHE] = "render",
305 [GFX6_SFID_DATAPORT_CONSTANT_CACHE] = "const",
306 [GFX7_SFID_DATAPORT_DATA_CACHE] = "data",
307 [GFX7_SFID_PIXEL_INTERPOLATOR] = "pixel interp",
308 [HSW_SFID_DATAPORT_DATA_CACHE_1] = "dp data 1",
309 [HSW_SFID_CRE] = "cre",
310 };
311
312 static const char *const gfx7_gateway_subfuncid[8] = {
313 [ELK_MESSAGE_GATEWAY_SFID_OPEN_GATEWAY] = "open",
314 [ELK_MESSAGE_GATEWAY_SFID_CLOSE_GATEWAY] = "close",
315 [ELK_MESSAGE_GATEWAY_SFID_FORWARD_MSG] = "forward msg",
316 [ELK_MESSAGE_GATEWAY_SFID_GET_TIMESTAMP] = "get timestamp",
317 [ELK_MESSAGE_GATEWAY_SFID_BARRIER_MSG] = "barrier msg",
318 [ELK_MESSAGE_GATEWAY_SFID_UPDATE_GATEWAY_STATE] = "update state",
319 [ELK_MESSAGE_GATEWAY_SFID_MMIO_READ_WRITE] = "mmio read/write",
320 };
321
322 static const char *const gfx4_dp_read_port_msg_type[4] = {
323 [0b00] = "OWord Block Read",
324 [0b01] = "OWord Dual Block Read",
325 [0b10] = "Media Block Read",
326 [0b11] = "DWord Scattered Read",
327 };
328
329 static const char *const g45_dp_read_port_msg_type[8] = {
330 [0b000] = "OWord Block Read",
331 [0b010] = "OWord Dual Block Read",
332 [0b100] = "Media Block Read",
333 [0b110] = "DWord Scattered Read",
334 [0b001] = "Render Target UNORM Read",
335 [0b011] = "AVC Loop Filter Read",
336 };
337
338 static const char *const dp_write_port_msg_type[8] = {
339 [0b000] = "OWord block write",
340 [0b001] = "OWord dual block write",
341 [0b010] = "media block write",
342 [0b011] = "DWord scattered write",
343 [0b100] = "RT write",
344 [0b101] = "streamed VB write",
345 [0b110] = "RT UNORM write", /* G45+ */
346 [0b111] = "flush render cache",
347 };
348
349 static const char *const dp_rc_msg_type_gfx6[16] = {
350 [ELK_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
351 [GFX6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
352 [GFX6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
353 [GFX6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read",
354 [GFX6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] =
355 "OWORD unaligned block read",
356 [GFX6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read",
357 [GFX6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write",
358 [GFX6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write",
359 [GFX6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] =
360 "OWORD dual block write",
361 [GFX6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write",
362 [GFX6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] =
363 "DWORD scattered write",
364 [GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write",
365 [GFX6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write",
366 [GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORM write",
367 };
368
369 static const char *const dp_rc_msg_type_gfx7[16] = {
370 [GFX7_DATAPORT_RC_MEDIA_BLOCK_READ] = "media block read",
371 [GFX7_DATAPORT_RC_TYPED_SURFACE_READ] = "typed surface read",
372 [GFX7_DATAPORT_RC_TYPED_ATOMIC_OP] = "typed atomic op",
373 [GFX7_DATAPORT_RC_MEMORY_FENCE] = "memory fence",
374 [GFX7_DATAPORT_RC_MEDIA_BLOCK_WRITE] = "media block write",
375 [GFX7_DATAPORT_RC_RENDER_TARGET_WRITE] = "RT write",
376 [GFX7_DATAPORT_RC_TYPED_SURFACE_WRITE] = "typed surface write"
377 };
378
379 static const char *const *
dp_rc_msg_type(const struct intel_device_info * devinfo)380 dp_rc_msg_type(const struct intel_device_info *devinfo)
381 {
382 return (devinfo->ver >= 7 ? dp_rc_msg_type_gfx7 :
383 devinfo->ver >= 6 ? dp_rc_msg_type_gfx6 :
384 dp_write_port_msg_type);
385 }
386
387 static const char *const m_rt_write_subtype[] = {
388 [0b000] = "SIMD16",
389 [0b001] = "SIMD16/RepData",
390 [0b010] = "SIMD8/DualSrcLow",
391 [0b011] = "SIMD8/DualSrcHigh",
392 [0b100] = "SIMD8",
393 [0b101] = "SIMD8/ImageWrite", /* Gfx6+ */
394 [0b111] = "SIMD16/RepData-111", /* no idea how this is different than 1 */
395 };
396
397 static const char *const dp_dc0_msg_type_gfx7[16] = {
398 [GFX7_DATAPORT_DC_OWORD_BLOCK_READ] = "DC OWORD block read",
399 [GFX7_DATAPORT_DC_UNALIGNED_OWORD_BLOCK_READ] =
400 "DC unaligned OWORD block read",
401 [GFX7_DATAPORT_DC_OWORD_DUAL_BLOCK_READ] = "DC OWORD dual block read",
402 [GFX7_DATAPORT_DC_DWORD_SCATTERED_READ] = "DC DWORD scattered read",
403 [GFX7_DATAPORT_DC_BYTE_SCATTERED_READ] = "DC byte scattered read",
404 [GFX7_DATAPORT_DC_UNTYPED_SURFACE_READ] = "DC untyped surface read",
405 [GFX7_DATAPORT_DC_UNTYPED_ATOMIC_OP] = "DC untyped atomic",
406 [GFX7_DATAPORT_DC_MEMORY_FENCE] = "DC mfence",
407 [GFX7_DATAPORT_DC_OWORD_BLOCK_WRITE] = "DC OWORD block write",
408 [GFX7_DATAPORT_DC_OWORD_DUAL_BLOCK_WRITE] = "DC OWORD dual block write",
409 [GFX7_DATAPORT_DC_DWORD_SCATTERED_WRITE] = "DC DWORD scatterd write",
410 [GFX7_DATAPORT_DC_BYTE_SCATTERED_WRITE] = "DC byte scattered write",
411 [GFX7_DATAPORT_DC_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
412 };
413
414 static const char *const dp_oword_block_rw[8] = {
415 [ELK_DATAPORT_OWORD_BLOCK_1_OWORDLOW] = "1-low",
416 [ELK_DATAPORT_OWORD_BLOCK_1_OWORDHIGH] = "1-high",
417 [ELK_DATAPORT_OWORD_BLOCK_2_OWORDS] = "2",
418 [ELK_DATAPORT_OWORD_BLOCK_4_OWORDS] = "4",
419 [ELK_DATAPORT_OWORD_BLOCK_8_OWORDS] = "8",
420 };
421
422 static const char *const dp_dc1_msg_type_hsw[32] = {
423 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ] = "untyped surface read",
424 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP] = "DC untyped atomic op",
425 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2] =
426 "DC untyped 4x2 atomic op",
427 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_READ] = "DC media block read",
428 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ] = "DC typed surface read",
429 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP] = "DC typed atomic",
430 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2] = "DC typed 4x2 atomic op",
431 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
432 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_WRITE] = "DC media block write",
433 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP] = "DC atomic counter op",
434 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2] =
435 "DC 4x2 atomic counter op",
436 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE] = "DC typed surface write",
437 [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_READ] = "DC A64 untyped surface read",
438 [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_OP] = "DC A64 untyped atomic op",
439 [GFX8_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_READ] = "DC A64 oword block read",
440 [GFX8_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_WRITE] = "DC A64 oword block write",
441 [GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_WRITE] = "DC A64 untyped surface write",
442 [GFX8_DATAPORT_DC_PORT1_A64_SCATTERED_WRITE] = "DC A64 scattered write",
443 };
444
445 static const char *const aop[16] = {
446 [ELK_AOP_AND] = "and",
447 [ELK_AOP_OR] = "or",
448 [ELK_AOP_XOR] = "xor",
449 [ELK_AOP_MOV] = "mov",
450 [ELK_AOP_INC] = "inc",
451 [ELK_AOP_DEC] = "dec",
452 [ELK_AOP_ADD] = "add",
453 [ELK_AOP_SUB] = "sub",
454 [ELK_AOP_REVSUB] = "revsub",
455 [ELK_AOP_IMAX] = "imax",
456 [ELK_AOP_IMIN] = "imin",
457 [ELK_AOP_UMAX] = "umax",
458 [ELK_AOP_UMIN] = "umin",
459 [ELK_AOP_CMPWR] = "cmpwr",
460 [ELK_AOP_PREDEC] = "predec",
461 };
462
463 static const char * const pixel_interpolator_msg_types[4] = {
464 [GFX7_PIXEL_INTERPOLATOR_LOC_SHARED_OFFSET] = "per_message_offset",
465 [GFX7_PIXEL_INTERPOLATOR_LOC_SAMPLE] = "sample_position",
466 [GFX7_PIXEL_INTERPOLATOR_LOC_CENTROID] = "centroid",
467 [GFX7_PIXEL_INTERPOLATOR_LOC_PER_SLOT_OFFSET] = "per_slot_offset",
468 };
469
470 static const char *const math_function[16] = {
471 [ELK_MATH_FUNCTION_INV] = "inv",
472 [ELK_MATH_FUNCTION_LOG] = "log",
473 [ELK_MATH_FUNCTION_EXP] = "exp",
474 [ELK_MATH_FUNCTION_SQRT] = "sqrt",
475 [ELK_MATH_FUNCTION_RSQ] = "rsq",
476 [ELK_MATH_FUNCTION_SIN] = "sin",
477 [ELK_MATH_FUNCTION_COS] = "cos",
478 [ELK_MATH_FUNCTION_SINCOS] = "sincos",
479 [ELK_MATH_FUNCTION_FDIV] = "fdiv",
480 [ELK_MATH_FUNCTION_POW] = "pow",
481 [ELK_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
482 [ELK_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
483 [ELK_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
484 [GFX8_MATH_FUNCTION_INVM] = "invm",
485 [GFX8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
486 };
487
488 static const char *const math_saturate[2] = {
489 [0] = "",
490 [1] = "sat"
491 };
492
493 static const char *const math_signed[2] = {
494 [0] = "",
495 [1] = "signed"
496 };
497
498 static const char *const math_scalar[2] = {
499 [0] = "",
500 [1] = "scalar"
501 };
502
503 static const char *const math_precision[2] = {
504 [0] = "",
505 [1] = "partial_precision"
506 };
507
508 static const char *const gfx5_urb_opcode[] = {
509 [0] = "urb_write",
510 [1] = "ff_sync",
511 };
512
513 static const char *const gfx7_urb_opcode[] = {
514 [ELK_URB_OPCODE_WRITE_HWORD] = "write HWord",
515 [ELK_URB_OPCODE_WRITE_OWORD] = "write OWord",
516 [ELK_URB_OPCODE_READ_HWORD] = "read HWord",
517 [ELK_URB_OPCODE_READ_OWORD] = "read OWord",
518 [GFX7_URB_OPCODE_ATOMIC_MOV] = "atomic mov", /* Gfx7+ */
519 [GFX7_URB_OPCODE_ATOMIC_INC] = "atomic inc", /* Gfx7+ */
520 [GFX8_URB_OPCODE_ATOMIC_ADD] = "atomic add", /* Gfx8+ */
521 [GFX8_URB_OPCODE_SIMD8_WRITE] = "SIMD8 write", /* Gfx8+ */
522 [GFX8_URB_OPCODE_SIMD8_READ] = "SIMD8 read", /* Gfx8+ */
523 /* [9-15] - reserved */
524 };
525
526 static const char *const urb_swizzle[4] = {
527 [ELK_URB_SWIZZLE_NONE] = "",
528 [ELK_URB_SWIZZLE_INTERLEAVE] = "interleave",
529 [ELK_URB_SWIZZLE_TRANSPOSE] = "transpose",
530 };
531
532 static const char *const urb_allocate[2] = {
533 [0] = "",
534 [1] = "allocate"
535 };
536
537 static const char *const urb_used[2] = {
538 [0] = "",
539 [1] = "used"
540 };
541
542 static const char *const urb_complete[2] = {
543 [0] = "",
544 [1] = "complete"
545 };
546
547 static const char *const gfx5_sampler_msg_type[] = {
548 [GFX5_SAMPLER_MESSAGE_SAMPLE] = "sample",
549 [GFX5_SAMPLER_MESSAGE_SAMPLE_BIAS] = "sample_b",
550 [GFX5_SAMPLER_MESSAGE_SAMPLE_LOD] = "sample_l",
551 [GFX5_SAMPLER_MESSAGE_SAMPLE_COMPARE] = "sample_c",
552 [GFX5_SAMPLER_MESSAGE_SAMPLE_DERIVS] = "sample_d",
553 [GFX5_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE] = "sample_b_c",
554 [GFX5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE] = "sample_l_c",
555 [GFX5_SAMPLER_MESSAGE_SAMPLE_LD] = "ld",
556 [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4] = "gather4",
557 [GFX5_SAMPLER_MESSAGE_LOD] = "lod",
558 [GFX5_SAMPLER_MESSAGE_SAMPLE_RESINFO] = "resinfo",
559 [GFX6_SAMPLER_MESSAGE_SAMPLE_SAMPLEINFO] = "sampleinfo",
560 [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_C] = "gather4_c",
561 [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO] = "gather4_po",
562 [GFX7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO_C] = "gather4_po_c",
563 [HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE] = "sample_d_c",
564 [GFX7_SAMPLER_MESSAGE_SAMPLE_LD_MCS] = "ld_mcs",
565 [GFX7_SAMPLER_MESSAGE_SAMPLE_LD2DMS] = "ld2dms",
566 [GFX7_SAMPLER_MESSAGE_SAMPLE_LD2DSS] = "ld2dss",
567 };
568
569 static const char *const gfx5_sampler_simd_mode[7] = {
570 [ELK_SAMPLER_SIMD_MODE_SIMD4X2] = "SIMD4x2",
571 [ELK_SAMPLER_SIMD_MODE_SIMD8] = "SIMD8",
572 [ELK_SAMPLER_SIMD_MODE_SIMD16] = "SIMD16",
573 [ELK_SAMPLER_SIMD_MODE_SIMD32_64] = "SIMD32/64",
574 };
575
576 static const char *const sampler_target_format[4] = {
577 [0] = "F",
578 [2] = "UD",
579 [3] = "D"
580 };
581
582 static int column;
583
584 static int
string(FILE * file,const char * string)585 string(FILE *file, const char *string)
586 {
587 fputs(string, file);
588 column += strlen(string);
589 return 0;
590 }
591
592 static int
593 format(FILE *f, const char *format, ...) PRINTFLIKE(2, 3);
594
595 static int
format(FILE * f,const char * format,...)596 format(FILE *f, const char *format, ...)
597 {
598 char buf[1024];
599 va_list args;
600 va_start(args, format);
601
602 vsnprintf(buf, sizeof(buf) - 1, format, args);
603 va_end(args);
604 string(f, buf);
605 return 0;
606 }
607
608 static int
newline(FILE * f)609 newline(FILE *f)
610 {
611 putc('\n', f);
612 column = 0;
613 return 0;
614 }
615
616 static int
pad(FILE * f,int c)617 pad(FILE *f, int c)
618 {
619 do
620 string(f, " ");
621 while (column < c);
622 return 0;
623 }
624
625 static int
control(FILE * file,const char * name,const char * const ctrl[],unsigned id,int * space)626 control(FILE *file, const char *name, const char *const ctrl[],
627 unsigned id, int *space)
628 {
629 if (!ctrl[id]) {
630 fprintf(file, "*** invalid %s value %d ", name, id);
631 return 1;
632 }
633 if (ctrl[id][0]) {
634 if (space && *space)
635 string(file, " ");
636 string(file, ctrl[id]);
637 if (space)
638 *space = 1;
639 }
640 return 0;
641 }
642
643 static int
print_opcode(FILE * file,const struct elk_isa_info * isa,enum elk_opcode id)644 print_opcode(FILE *file, const struct elk_isa_info *isa,
645 enum elk_opcode id)
646 {
647 const struct elk_opcode_desc *desc = elk_opcode_desc(isa, id);
648 if (!desc) {
649 format(file, "*** invalid opcode value %d ", id);
650 return 1;
651 }
652 string(file, desc->name);
653 return 0;
654 }
655
656 static int
reg(FILE * file,unsigned _reg_file,unsigned _reg_nr)657 reg(FILE *file, unsigned _reg_file, unsigned _reg_nr)
658 {
659 int err = 0;
660
661 /* Clear the Compr4 instruction compression bit. */
662 if (_reg_file == ELK_MESSAGE_REGISTER_FILE)
663 _reg_nr &= ~ELK_MRF_COMPR4;
664
665 if (_reg_file == ELK_ARCHITECTURE_REGISTER_FILE) {
666 switch (_reg_nr & 0xf0) {
667 case ELK_ARF_NULL:
668 string(file, "null");
669 break;
670 case ELK_ARF_ADDRESS:
671 format(file, "a%d", _reg_nr & 0x0f);
672 break;
673 case ELK_ARF_ACCUMULATOR:
674 format(file, "acc%d", _reg_nr & 0x0f);
675 break;
676 case ELK_ARF_FLAG:
677 format(file, "f%d", _reg_nr & 0x0f);
678 break;
679 case ELK_ARF_MASK:
680 format(file, "mask%d", _reg_nr & 0x0f);
681 break;
682 case ELK_ARF_MASK_STACK:
683 format(file, "ms%d", _reg_nr & 0x0f);
684 break;
685 case ELK_ARF_MASK_STACK_DEPTH:
686 format(file, "msd%d", _reg_nr & 0x0f);
687 break;
688 case ELK_ARF_STATE:
689 format(file, "sr%d", _reg_nr & 0x0f);
690 break;
691 case ELK_ARF_CONTROL:
692 format(file, "cr%d", _reg_nr & 0x0f);
693 break;
694 case ELK_ARF_NOTIFICATION_COUNT:
695 format(file, "n%d", _reg_nr & 0x0f);
696 break;
697 case ELK_ARF_IP:
698 string(file, "ip");
699 return -1;
700 break;
701 case ELK_ARF_TDR:
702 format(file, "tdr0");
703 return -1;
704 case ELK_ARF_TIMESTAMP:
705 format(file, "tm%d", _reg_nr & 0x0f);
706 break;
707 default:
708 format(file, "ARF%d", _reg_nr);
709 break;
710 }
711 } else {
712 err |= control(file, "src reg file", reg_file, _reg_file, NULL);
713 format(file, "%d", _reg_nr);
714 }
715 return err;
716 }
717
718 static int
dest(FILE * file,const struct elk_isa_info * isa,const elk_inst * inst)719 dest(FILE *file, const struct elk_isa_info *isa, const elk_inst *inst)
720 {
721 const struct intel_device_info *devinfo = isa->devinfo;
722 enum elk_reg_type type = elk_inst_dst_type(devinfo, inst);
723 unsigned elem_size = elk_reg_type_to_size(type);
724 int err = 0;
725
726 if (elk_inst_access_mode(devinfo, inst) == ELK_ALIGN_1) {
727 if (elk_inst_dst_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
728 err |= reg(file, elk_inst_dst_reg_file(devinfo, inst),
729 elk_inst_dst_da_reg_nr(devinfo, inst));
730 if (err == -1)
731 return 0;
732 if (elk_inst_dst_da1_subreg_nr(devinfo, inst))
733 format(file, ".%"PRIu64, elk_inst_dst_da1_subreg_nr(devinfo, inst) /
734 elem_size);
735 string(file, "<");
736 err |= control(file, "horiz stride", horiz_stride,
737 elk_inst_dst_hstride(devinfo, inst), NULL);
738 string(file, ">");
739 string(file, elk_reg_type_to_letters(type));
740 } else {
741 string(file, "g[a0");
742 if (elk_inst_dst_ia_subreg_nr(devinfo, inst))
743 format(file, ".%"PRIu64, elk_inst_dst_ia_subreg_nr(devinfo, inst) /
744 elem_size);
745 if (elk_inst_dst_ia1_addr_imm(devinfo, inst))
746 format(file, " %d", elk_inst_dst_ia1_addr_imm(devinfo, inst));
747 string(file, "]<");
748 err |= control(file, "horiz stride", horiz_stride,
749 elk_inst_dst_hstride(devinfo, inst), NULL);
750 string(file, ">");
751 string(file, elk_reg_type_to_letters(type));
752 }
753 } else {
754 if (elk_inst_dst_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
755 err |= reg(file, elk_inst_dst_reg_file(devinfo, inst),
756 elk_inst_dst_da_reg_nr(devinfo, inst));
757 if (err == -1)
758 return 0;
759 if (elk_inst_dst_da16_subreg_nr(devinfo, inst))
760 format(file, ".%u", 16 / elem_size);
761 string(file, "<1>");
762 err |= control(file, "writemask", writemask,
763 elk_inst_da16_writemask(devinfo, inst), NULL);
764 string(file, elk_reg_type_to_letters(type));
765 } else {
766 err = 1;
767 string(file, "Indirect align16 address mode not supported");
768 }
769 }
770
771 return 0;
772 }
773
774 static int
dest_3src(FILE * file,const struct intel_device_info * devinfo,const elk_inst * inst)775 dest_3src(FILE *file, const struct intel_device_info *devinfo,
776 const elk_inst *inst)
777 {
778 bool is_align1 = elk_inst_3src_access_mode(devinfo, inst) == ELK_ALIGN_1;
779 int err = 0;
780 uint32_t reg_file;
781 unsigned subreg_nr;
782 enum elk_reg_type type;
783
784 if (is_align1)
785 return 0;
786
787 if (devinfo->ver == 6 && elk_inst_3src_a16_dst_reg_file(devinfo, inst))
788 reg_file = ELK_MESSAGE_REGISTER_FILE;
789 else
790 reg_file = ELK_GENERAL_REGISTER_FILE;
791
792 err |= reg(file, reg_file, elk_inst_3src_dst_reg_nr(devinfo, inst));
793 if (err == -1)
794 return 0;
795
796 type = elk_inst_3src_a16_dst_type(devinfo, inst);
797 subreg_nr = elk_inst_3src_a16_dst_subreg_nr(devinfo, inst) * 4;
798 subreg_nr /= elk_reg_type_to_size(type);
799
800 if (subreg_nr)
801 format(file, ".%u", subreg_nr);
802 string(file, "<1>");
803
804 if (!is_align1) {
805 err |= control(file, "writemask", writemask,
806 elk_inst_3src_a16_dst_writemask(devinfo, inst), NULL);
807 }
808 string(file, elk_reg_type_to_letters(type));
809
810 return 0;
811 }
812
813 static int
src_align1_region(FILE * file,unsigned _vert_stride,unsigned _width,unsigned _horiz_stride)814 src_align1_region(FILE *file,
815 unsigned _vert_stride, unsigned _width,
816 unsigned _horiz_stride)
817 {
818 int err = 0;
819 string(file, "<");
820 err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
821 string(file, ",");
822 err |= control(file, "width", width, _width, NULL);
823 string(file, ",");
824 err |= control(file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
825 string(file, ">");
826 return err;
827 }
828
829 static int
src_da1(FILE * file,const struct intel_device_info * devinfo,unsigned opcode,enum elk_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)830 src_da1(FILE *file,
831 const struct intel_device_info *devinfo,
832 unsigned opcode,
833 enum elk_reg_type type, unsigned _reg_file,
834 unsigned _vert_stride, unsigned _width, unsigned _horiz_stride,
835 unsigned reg_num, unsigned sub_reg_num, unsigned __abs,
836 unsigned _negate)
837 {
838 int err = 0;
839
840 if (devinfo->ver >= 8 && is_logic_instruction(opcode))
841 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
842 else
843 err |= control(file, "negate", m_negate, _negate, NULL);
844
845 err |= control(file, "abs", _abs, __abs, NULL);
846
847 err |= reg(file, _reg_file, reg_num);
848 if (err == -1)
849 return 0;
850 if (sub_reg_num) {
851 unsigned elem_size = elk_reg_type_to_size(type);
852 format(file, ".%d", sub_reg_num / elem_size); /* use formal style like spec */
853 }
854 src_align1_region(file, _vert_stride, _width, _horiz_stride);
855 string(file, elk_reg_type_to_letters(type));
856 return err;
857 }
858
859 static int
src_ia1(FILE * file,const struct intel_device_info * devinfo,unsigned opcode,enum elk_reg_type type,int _addr_imm,unsigned _addr_subreg_nr,unsigned _negate,unsigned __abs,unsigned _horiz_stride,unsigned _width,unsigned _vert_stride)860 src_ia1(FILE *file,
861 const struct intel_device_info *devinfo,
862 unsigned opcode,
863 enum elk_reg_type type,
864 int _addr_imm,
865 unsigned _addr_subreg_nr,
866 unsigned _negate,
867 unsigned __abs,
868 unsigned _horiz_stride, unsigned _width, unsigned _vert_stride)
869 {
870 int err = 0;
871
872 if (devinfo->ver >= 8 && is_logic_instruction(opcode))
873 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
874 else
875 err |= control(file, "negate", m_negate, _negate, NULL);
876
877 err |= control(file, "abs", _abs, __abs, NULL);
878
879 string(file, "g[a0");
880 if (_addr_subreg_nr)
881 format(file, ".%d", _addr_subreg_nr);
882 if (_addr_imm)
883 format(file, " %d", _addr_imm);
884 string(file, "]");
885 src_align1_region(file, _vert_stride, _width, _horiz_stride);
886 string(file, elk_reg_type_to_letters(type));
887 return err;
888 }
889
890 static int
src_swizzle(FILE * file,unsigned swiz)891 src_swizzle(FILE *file, unsigned swiz)
892 {
893 unsigned x = ELK_GET_SWZ(swiz, ELK_CHANNEL_X);
894 unsigned y = ELK_GET_SWZ(swiz, ELK_CHANNEL_Y);
895 unsigned z = ELK_GET_SWZ(swiz, ELK_CHANNEL_Z);
896 unsigned w = ELK_GET_SWZ(swiz, ELK_CHANNEL_W);
897 int err = 0;
898
899 if (x == y && x == z && x == w) {
900 string(file, ".");
901 err |= control(file, "channel select", chan_sel, x, NULL);
902 } else if (swiz != ELK_SWIZZLE_XYZW) {
903 string(file, ".");
904 err |= control(file, "channel select", chan_sel, x, NULL);
905 err |= control(file, "channel select", chan_sel, y, NULL);
906 err |= control(file, "channel select", chan_sel, z, NULL);
907 err |= control(file, "channel select", chan_sel, w, NULL);
908 }
909 return err;
910 }
911
912 static int
src_da16(FILE * file,const struct intel_device_info * devinfo,unsigned opcode,enum elk_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)913 src_da16(FILE *file,
914 const struct intel_device_info *devinfo,
915 unsigned opcode,
916 enum elk_reg_type type,
917 unsigned _reg_file,
918 unsigned _vert_stride,
919 unsigned _reg_nr,
920 unsigned _subreg_nr,
921 unsigned __abs,
922 unsigned _negate,
923 unsigned swz_x, unsigned swz_y, unsigned swz_z, unsigned swz_w)
924 {
925 int err = 0;
926
927 if (devinfo->ver >= 8 && is_logic_instruction(opcode))
928 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
929 else
930 err |= control(file, "negate", m_negate, _negate, NULL);
931
932 err |= control(file, "abs", _abs, __abs, NULL);
933
934 err |= reg(file, _reg_file, _reg_nr);
935 if (err == -1)
936 return 0;
937 if (_subreg_nr) {
938 unsigned elem_size = elk_reg_type_to_size(type);
939
940 /* bit4 for subreg number byte addressing. Make this same meaning as
941 in da1 case, so output looks consistent. */
942 format(file, ".%d", 16 / elem_size);
943 }
944 string(file, "<");
945 err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
946 string(file, ">");
947 err |= src_swizzle(file, ELK_SWIZZLE4(swz_x, swz_y, swz_z, swz_w));
948 string(file, elk_reg_type_to_letters(type));
949 return err;
950 }
951
952 static enum elk_vertical_stride
vstride_from_align1_3src_vstride(const struct intel_device_info * devinfo,enum gfx10_align1_3src_vertical_stride vstride)953 vstride_from_align1_3src_vstride(const struct intel_device_info *devinfo,
954 enum gfx10_align1_3src_vertical_stride vstride)
955 {
956 switch (vstride) {
957 case ELK_ALIGN1_3SRC_VERTICAL_STRIDE_0: return ELK_VERTICAL_STRIDE_0;
958 case ELK_ALIGN1_3SRC_VERTICAL_STRIDE_2: return ELK_VERTICAL_STRIDE_2;
959 case ELK_ALIGN1_3SRC_VERTICAL_STRIDE_4: return ELK_VERTICAL_STRIDE_4;
960 case ELK_ALIGN1_3SRC_VERTICAL_STRIDE_8: return ELK_VERTICAL_STRIDE_8;
961 default:
962 unreachable("not reached");
963 }
964 }
965
966 static enum elk_horizontal_stride
hstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)967 hstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)
968 {
969 switch (hstride) {
970 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return ELK_HORIZONTAL_STRIDE_0;
971 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return ELK_HORIZONTAL_STRIDE_1;
972 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return ELK_HORIZONTAL_STRIDE_2;
973 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return ELK_HORIZONTAL_STRIDE_4;
974 default:
975 unreachable("not reached");
976 }
977 }
978
979 static enum elk_vertical_stride
vstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)980 vstride_from_align1_3src_hstride(enum gfx10_align1_3src_src_horizontal_stride hstride)
981 {
982 switch (hstride) {
983 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return ELK_VERTICAL_STRIDE_0;
984 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return ELK_VERTICAL_STRIDE_1;
985 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return ELK_VERTICAL_STRIDE_2;
986 case ELK_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return ELK_VERTICAL_STRIDE_4;
987 default:
988 unreachable("not reached");
989 }
990 }
991
992 /* From "GFX10 Regioning Rules for Align1 Ternary Operations" in the
993 * "Register Region Restrictions" documentation
994 */
995 static enum elk_width
implied_width(enum elk_vertical_stride _vert_stride,enum elk_horizontal_stride _horiz_stride)996 implied_width(enum elk_vertical_stride _vert_stride,
997 enum elk_horizontal_stride _horiz_stride)
998 {
999 /* "1. Width is 1 when Vertical and Horizontal Strides are both zero." */
1000 if (_vert_stride == ELK_VERTICAL_STRIDE_0 &&
1001 _horiz_stride == ELK_HORIZONTAL_STRIDE_0) {
1002 return ELK_WIDTH_1;
1003
1004 /* "2. Width is equal to vertical stride when Horizontal Stride is zero." */
1005 } else if (_horiz_stride == ELK_HORIZONTAL_STRIDE_0) {
1006 switch (_vert_stride) {
1007 case ELK_VERTICAL_STRIDE_1: return ELK_WIDTH_1;
1008 case ELK_VERTICAL_STRIDE_2: return ELK_WIDTH_2;
1009 case ELK_VERTICAL_STRIDE_4: return ELK_WIDTH_4;
1010 case ELK_VERTICAL_STRIDE_8: return ELK_WIDTH_8;
1011 case ELK_VERTICAL_STRIDE_0:
1012 default:
1013 unreachable("not reached");
1014 }
1015
1016 } else {
1017 /* FINISHME: Implement these: */
1018
1019 /* "3. Width is equal to Vertical Stride/Horizontal Stride when both
1020 * Strides are non-zero.
1021 *
1022 * 4. Vertical Stride must not be zero if Horizontal Stride is non-zero.
1023 * This implies Vertical Stride is always greater than Horizontal
1024 * Stride."
1025 *
1026 * Given these statements and the knowledge that the stride and width
1027 * values are encoded in logarithmic form, we can perform the division
1028 * by just subtracting.
1029 */
1030 return _vert_stride - _horiz_stride;
1031 }
1032 }
1033
1034 static int
src0_3src(FILE * file,const struct intel_device_info * devinfo,const elk_inst * inst)1035 src0_3src(FILE *file, const struct intel_device_info *devinfo,
1036 const elk_inst *inst)
1037 {
1038 int err = 0;
1039 unsigned reg_nr, subreg_nr;
1040 enum elk_reg_file _file;
1041 enum elk_reg_type type;
1042 enum elk_vertical_stride _vert_stride;
1043 enum elk_width _width;
1044 enum elk_horizontal_stride _horiz_stride;
1045 bool is_scalar_region;
1046 bool is_align1 = elk_inst_3src_access_mode(devinfo, inst) == ELK_ALIGN_1;
1047
1048 if (is_align1)
1049 return 0;
1050
1051 _file = ELK_GENERAL_REGISTER_FILE;
1052 reg_nr = elk_inst_3src_src0_reg_nr(devinfo, inst);
1053 subreg_nr = elk_inst_3src_a16_src0_subreg_nr(devinfo, inst) * 4;
1054 type = elk_inst_3src_a16_src_type(devinfo, inst);
1055
1056 if (elk_inst_3src_a16_src0_rep_ctrl(devinfo, inst)) {
1057 _vert_stride = ELK_VERTICAL_STRIDE_0;
1058 _width = ELK_WIDTH_1;
1059 _horiz_stride = ELK_HORIZONTAL_STRIDE_0;
1060 } else {
1061 _vert_stride = ELK_VERTICAL_STRIDE_4;
1062 _width = ELK_WIDTH_4;
1063 _horiz_stride = ELK_HORIZONTAL_STRIDE_1;
1064 }
1065
1066 is_scalar_region = _vert_stride == ELK_VERTICAL_STRIDE_0 &&
1067 _width == ELK_WIDTH_1 &&
1068 _horiz_stride == ELK_HORIZONTAL_STRIDE_0;
1069
1070 subreg_nr /= elk_reg_type_to_size(type);
1071
1072 err |= control(file, "negate", m_negate,
1073 elk_inst_3src_src0_negate(devinfo, inst), NULL);
1074 err |= control(file, "abs", _abs, elk_inst_3src_src0_abs(devinfo, inst), NULL);
1075
1076 err |= reg(file, _file, reg_nr);
1077 if (err == -1)
1078 return 0;
1079 if (subreg_nr || is_scalar_region)
1080 format(file, ".%d", subreg_nr);
1081 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1082 if (!is_scalar_region && !is_align1)
1083 err |= src_swizzle(file, elk_inst_3src_a16_src0_swizzle(devinfo, inst));
1084 string(file, elk_reg_type_to_letters(type));
1085 return err;
1086 }
1087
1088 static int
src1_3src(FILE * file,const struct intel_device_info * devinfo,const elk_inst * inst)1089 src1_3src(FILE *file, const struct intel_device_info *devinfo,
1090 const elk_inst *inst)
1091 {
1092 int err = 0;
1093 unsigned reg_nr, subreg_nr;
1094 enum elk_reg_file _file;
1095 enum elk_reg_type type;
1096 enum elk_vertical_stride _vert_stride;
1097 enum elk_width _width;
1098 enum elk_horizontal_stride _horiz_stride;
1099 bool is_scalar_region;
1100 bool is_align1 = elk_inst_3src_access_mode(devinfo, inst) == ELK_ALIGN_1;
1101
1102 if (is_align1)
1103 return 0;
1104
1105 _file = ELK_GENERAL_REGISTER_FILE;
1106 reg_nr = elk_inst_3src_src1_reg_nr(devinfo, inst);
1107 subreg_nr = elk_inst_3src_a16_src1_subreg_nr(devinfo, inst) * 4;
1108 type = elk_inst_3src_a16_src_type(devinfo, inst);
1109
1110 if (elk_inst_3src_a16_src1_rep_ctrl(devinfo, inst)) {
1111 _vert_stride = ELK_VERTICAL_STRIDE_0;
1112 _width = ELK_WIDTH_1;
1113 _horiz_stride = ELK_HORIZONTAL_STRIDE_0;
1114 } else {
1115 _vert_stride = ELK_VERTICAL_STRIDE_4;
1116 _width = ELK_WIDTH_4;
1117 _horiz_stride = ELK_HORIZONTAL_STRIDE_1;
1118 }
1119
1120 is_scalar_region = _vert_stride == ELK_VERTICAL_STRIDE_0 &&
1121 _width == ELK_WIDTH_1 &&
1122 _horiz_stride == ELK_HORIZONTAL_STRIDE_0;
1123
1124 subreg_nr /= elk_reg_type_to_size(type);
1125
1126 err |= control(file, "negate", m_negate,
1127 elk_inst_3src_src1_negate(devinfo, inst), NULL);
1128 err |= control(file, "abs", _abs, elk_inst_3src_src1_abs(devinfo, inst), NULL);
1129
1130 err |= reg(file, _file, reg_nr);
1131 if (err == -1)
1132 return 0;
1133 if (subreg_nr || is_scalar_region)
1134 format(file, ".%d", subreg_nr);
1135 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1136 if (!is_scalar_region && !is_align1)
1137 err |= src_swizzle(file, elk_inst_3src_a16_src1_swizzle(devinfo, inst));
1138 string(file, elk_reg_type_to_letters(type));
1139 return err;
1140 }
1141
1142 static int
src2_3src(FILE * file,const struct intel_device_info * devinfo,const elk_inst * inst)1143 src2_3src(FILE *file, const struct intel_device_info *devinfo,
1144 const elk_inst *inst)
1145 {
1146 int err = 0;
1147 unsigned reg_nr, subreg_nr;
1148 enum elk_reg_file _file;
1149 enum elk_reg_type type;
1150 enum elk_vertical_stride _vert_stride;
1151 enum elk_width _width;
1152 enum elk_horizontal_stride _horiz_stride;
1153 bool is_scalar_region;
1154 bool is_align1 = elk_inst_3src_access_mode(devinfo, inst) == ELK_ALIGN_1;
1155
1156 if (is_align1)
1157 return 0;
1158
1159 _file = ELK_GENERAL_REGISTER_FILE;
1160 reg_nr = elk_inst_3src_src2_reg_nr(devinfo, inst);
1161 subreg_nr = elk_inst_3src_a16_src2_subreg_nr(devinfo, inst) * 4;
1162 type = elk_inst_3src_a16_src_type(devinfo, inst);
1163
1164 if (elk_inst_3src_a16_src2_rep_ctrl(devinfo, inst)) {
1165 _vert_stride = ELK_VERTICAL_STRIDE_0;
1166 _width = ELK_WIDTH_1;
1167 _horiz_stride = ELK_HORIZONTAL_STRIDE_0;
1168 } else {
1169 _vert_stride = ELK_VERTICAL_STRIDE_4;
1170 _width = ELK_WIDTH_4;
1171 _horiz_stride = ELK_HORIZONTAL_STRIDE_1;
1172 }
1173
1174 is_scalar_region = _vert_stride == ELK_VERTICAL_STRIDE_0 &&
1175 _width == ELK_WIDTH_1 &&
1176 _horiz_stride == ELK_HORIZONTAL_STRIDE_0;
1177
1178 subreg_nr /= elk_reg_type_to_size(type);
1179
1180 err |= control(file, "negate", m_negate,
1181 elk_inst_3src_src2_negate(devinfo, inst), NULL);
1182 err |= control(file, "abs", _abs, elk_inst_3src_src2_abs(devinfo, inst), NULL);
1183
1184 err |= reg(file, _file, reg_nr);
1185 if (err == -1)
1186 return 0;
1187 if (subreg_nr || is_scalar_region)
1188 format(file, ".%d", subreg_nr);
1189 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1190 if (!is_scalar_region && !is_align1)
1191 err |= src_swizzle(file, elk_inst_3src_a16_src2_swizzle(devinfo, inst));
1192 string(file, elk_reg_type_to_letters(type));
1193 return err;
1194 }
1195
1196 static int
imm(FILE * file,const struct elk_isa_info * isa,enum elk_reg_type type,const elk_inst * inst)1197 imm(FILE *file, const struct elk_isa_info *isa, enum elk_reg_type type,
1198 const elk_inst *inst)
1199 {
1200 const struct intel_device_info *devinfo = isa->devinfo;
1201
1202 switch (type) {
1203 case ELK_REGISTER_TYPE_UQ:
1204 format(file, "0x%016"PRIx64"UQ", elk_inst_imm_uq(devinfo, inst));
1205 break;
1206 case ELK_REGISTER_TYPE_Q:
1207 format(file, "0x%016"PRIx64"Q", elk_inst_imm_uq(devinfo, inst));
1208 break;
1209 case ELK_REGISTER_TYPE_UD:
1210 format(file, "0x%08xUD", elk_inst_imm_ud(devinfo, inst));
1211 break;
1212 case ELK_REGISTER_TYPE_D:
1213 format(file, "%dD", elk_inst_imm_d(devinfo, inst));
1214 break;
1215 case ELK_REGISTER_TYPE_UW:
1216 format(file, "0x%04xUW", (uint16_t) elk_inst_imm_ud(devinfo, inst));
1217 break;
1218 case ELK_REGISTER_TYPE_W:
1219 format(file, "%dW", (int16_t) elk_inst_imm_d(devinfo, inst));
1220 break;
1221 case ELK_REGISTER_TYPE_UV:
1222 format(file, "0x%08xUV", elk_inst_imm_ud(devinfo, inst));
1223 break;
1224 case ELK_REGISTER_TYPE_VF:
1225 format(file, "0x%"PRIx64"VF", elk_inst_bits(inst, 127, 96));
1226 pad(file, 48);
1227 format(file, "/* [%-gF, %-gF, %-gF, %-gF]VF */",
1228 elk_vf_to_float(elk_inst_imm_ud(devinfo, inst)),
1229 elk_vf_to_float(elk_inst_imm_ud(devinfo, inst) >> 8),
1230 elk_vf_to_float(elk_inst_imm_ud(devinfo, inst) >> 16),
1231 elk_vf_to_float(elk_inst_imm_ud(devinfo, inst) >> 24));
1232 break;
1233 case ELK_REGISTER_TYPE_V:
1234 format(file, "0x%08xV", elk_inst_imm_ud(devinfo, inst));
1235 break;
1236 case ELK_REGISTER_TYPE_F:
1237 /* The DIM instruction's src0 uses an F type but contains a
1238 * 64-bit immediate
1239 */
1240 if (elk_inst_opcode(isa, inst) == ELK_OPCODE_DIM) {
1241 format(file, "0x%"PRIx64"F", elk_inst_bits(inst, 127, 64));
1242 pad(file, 48);
1243 format(file, "/* %-gF */", elk_inst_imm_df(devinfo, inst));
1244 } else {
1245 format(file, "0x%"PRIx64"F", elk_inst_bits(inst, 127, 96));
1246 pad(file, 48);
1247 format(file, " /* %-gF */", elk_inst_imm_f(devinfo, inst));
1248 }
1249 break;
1250 case ELK_REGISTER_TYPE_DF:
1251 format(file, "0x%016"PRIx64"DF", elk_inst_imm_uq(devinfo, inst));
1252 pad(file, 48);
1253 format(file, "/* %-gDF */", elk_inst_imm_df(devinfo, inst));
1254 break;
1255 case ELK_REGISTER_TYPE_HF:
1256 format(file, "0x%04xHF",
1257 (uint16_t) elk_inst_imm_ud(devinfo, inst));
1258 pad(file, 48);
1259 format(file, "/* %-gHF */",
1260 _mesa_half_to_float((uint16_t) elk_inst_imm_ud(devinfo, inst)));
1261 break;
1262 case ELK_REGISTER_TYPE_NF:
1263 case ELK_REGISTER_TYPE_UB:
1264 case ELK_REGISTER_TYPE_B:
1265 format(file, "*** invalid immediate type %d ", type);
1266 }
1267 return 0;
1268 }
1269
1270 static int
src_send_desc_ia(FILE * file,const struct intel_device_info * devinfo,unsigned _addr_subreg_nr)1271 src_send_desc_ia(FILE *file,
1272 const struct intel_device_info *devinfo,
1273 unsigned _addr_subreg_nr)
1274 {
1275 string(file, "a0");
1276 if (_addr_subreg_nr)
1277 format(file, ".%d", _addr_subreg_nr);
1278 format(file, "<0>UD");
1279
1280 return 0;
1281 }
1282
1283 static int
src0(FILE * file,const struct elk_isa_info * isa,const elk_inst * inst)1284 src0(FILE *file, const struct elk_isa_info *isa, const elk_inst *inst)
1285 {
1286 const struct intel_device_info *devinfo = isa->devinfo;
1287
1288 if (elk_inst_src0_reg_file(devinfo, inst) == ELK_IMMEDIATE_VALUE) {
1289 return imm(file, isa, elk_inst_src0_type(devinfo, inst), inst);
1290 } else if (elk_inst_access_mode(devinfo, inst) == ELK_ALIGN_1) {
1291 if (elk_inst_src0_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
1292 return src_da1(file,
1293 devinfo,
1294 elk_inst_opcode(isa, inst),
1295 elk_inst_src0_type(devinfo, inst),
1296 elk_inst_src0_reg_file(devinfo, inst),
1297 elk_inst_src0_vstride(devinfo, inst),
1298 elk_inst_src0_width(devinfo, inst),
1299 elk_inst_src0_hstride(devinfo, inst),
1300 elk_inst_src0_da_reg_nr(devinfo, inst),
1301 elk_inst_src0_da1_subreg_nr(devinfo, inst),
1302 elk_inst_src0_abs(devinfo, inst),
1303 elk_inst_src0_negate(devinfo, inst));
1304 } else {
1305 return src_ia1(file,
1306 devinfo,
1307 elk_inst_opcode(isa, inst),
1308 elk_inst_src0_type(devinfo, inst),
1309 elk_inst_src0_ia1_addr_imm(devinfo, inst),
1310 elk_inst_src0_ia_subreg_nr(devinfo, inst),
1311 elk_inst_src0_negate(devinfo, inst),
1312 elk_inst_src0_abs(devinfo, inst),
1313 elk_inst_src0_hstride(devinfo, inst),
1314 elk_inst_src0_width(devinfo, inst),
1315 elk_inst_src0_vstride(devinfo, inst));
1316 }
1317 } else {
1318 if (elk_inst_src0_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
1319 return src_da16(file,
1320 devinfo,
1321 elk_inst_opcode(isa, inst),
1322 elk_inst_src0_type(devinfo, inst),
1323 elk_inst_src0_reg_file(devinfo, inst),
1324 elk_inst_src0_vstride(devinfo, inst),
1325 elk_inst_src0_da_reg_nr(devinfo, inst),
1326 elk_inst_src0_da16_subreg_nr(devinfo, inst),
1327 elk_inst_src0_abs(devinfo, inst),
1328 elk_inst_src0_negate(devinfo, inst),
1329 elk_inst_src0_da16_swiz_x(devinfo, inst),
1330 elk_inst_src0_da16_swiz_y(devinfo, inst),
1331 elk_inst_src0_da16_swiz_z(devinfo, inst),
1332 elk_inst_src0_da16_swiz_w(devinfo, inst));
1333 } else {
1334 string(file, "Indirect align16 address mode not supported");
1335 return 1;
1336 }
1337 }
1338 }
1339
1340 static int
src1(FILE * file,const struct elk_isa_info * isa,const elk_inst * inst)1341 src1(FILE *file, const struct elk_isa_info *isa, const elk_inst *inst)
1342 {
1343 const struct intel_device_info *devinfo = isa->devinfo;
1344
1345 if (elk_inst_src1_reg_file(devinfo, inst) == ELK_IMMEDIATE_VALUE) {
1346 return imm(file, isa, elk_inst_src1_type(devinfo, inst), inst);
1347 } else if (elk_inst_access_mode(devinfo, inst) == ELK_ALIGN_1) {
1348 if (elk_inst_src1_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
1349 return src_da1(file,
1350 devinfo,
1351 elk_inst_opcode(isa, inst),
1352 elk_inst_src1_type(devinfo, inst),
1353 elk_inst_src1_reg_file(devinfo, inst),
1354 elk_inst_src1_vstride(devinfo, inst),
1355 elk_inst_src1_width(devinfo, inst),
1356 elk_inst_src1_hstride(devinfo, inst),
1357 elk_inst_src1_da_reg_nr(devinfo, inst),
1358 elk_inst_src1_da1_subreg_nr(devinfo, inst),
1359 elk_inst_src1_abs(devinfo, inst),
1360 elk_inst_src1_negate(devinfo, inst));
1361 } else {
1362 return src_ia1(file,
1363 devinfo,
1364 elk_inst_opcode(isa, inst),
1365 elk_inst_src1_type(devinfo, inst),
1366 elk_inst_src1_ia1_addr_imm(devinfo, inst),
1367 elk_inst_src1_ia_subreg_nr(devinfo, inst),
1368 elk_inst_src1_negate(devinfo, inst),
1369 elk_inst_src1_abs(devinfo, inst),
1370 elk_inst_src1_hstride(devinfo, inst),
1371 elk_inst_src1_width(devinfo, inst),
1372 elk_inst_src1_vstride(devinfo, inst));
1373 }
1374 } else {
1375 if (elk_inst_src1_address_mode(devinfo, inst) == ELK_ADDRESS_DIRECT) {
1376 return src_da16(file,
1377 devinfo,
1378 elk_inst_opcode(isa, inst),
1379 elk_inst_src1_type(devinfo, inst),
1380 elk_inst_src1_reg_file(devinfo, inst),
1381 elk_inst_src1_vstride(devinfo, inst),
1382 elk_inst_src1_da_reg_nr(devinfo, inst),
1383 elk_inst_src1_da16_subreg_nr(devinfo, inst),
1384 elk_inst_src1_abs(devinfo, inst),
1385 elk_inst_src1_negate(devinfo, inst),
1386 elk_inst_src1_da16_swiz_x(devinfo, inst),
1387 elk_inst_src1_da16_swiz_y(devinfo, inst),
1388 elk_inst_src1_da16_swiz_z(devinfo, inst),
1389 elk_inst_src1_da16_swiz_w(devinfo, inst));
1390 } else {
1391 string(file, "Indirect align16 address mode not supported");
1392 return 1;
1393 }
1394 }
1395 }
1396
1397 static int
qtr_ctrl(FILE * file,const struct intel_device_info * devinfo,const elk_inst * inst)1398 qtr_ctrl(FILE *file, const struct intel_device_info *devinfo,
1399 const elk_inst *inst)
1400 {
1401 int qtr_ctl = elk_inst_qtr_control(devinfo, inst);
1402 int exec_size = 1 << elk_inst_exec_size(devinfo, inst);
1403 const unsigned nib_ctl =
1404 devinfo->ver < 7 ? 0 : elk_inst_nib_control(devinfo, inst);
1405
1406 if (exec_size < 8 || nib_ctl) {
1407 format(file, " %dN", qtr_ctl * 2 + nib_ctl + 1);
1408 } else if (exec_size == 8) {
1409 switch (qtr_ctl) {
1410 case 0:
1411 string(file, " 1Q");
1412 break;
1413 case 1:
1414 string(file, " 2Q");
1415 break;
1416 case 2:
1417 string(file, " 3Q");
1418 break;
1419 case 3:
1420 string(file, " 4Q");
1421 break;
1422 }
1423 } else if (exec_size == 16) {
1424 if (qtr_ctl < 2)
1425 string(file, " 1H");
1426 else
1427 string(file, " 2H");
1428 }
1429 return 0;
1430 }
1431
1432 static bool
inst_has_type(const struct elk_isa_info * isa,const elk_inst * inst,enum elk_reg_type type)1433 inst_has_type(const struct elk_isa_info *isa,
1434 const elk_inst *inst,
1435 enum elk_reg_type type)
1436 {
1437 const struct intel_device_info *devinfo = isa->devinfo;
1438 const unsigned num_sources = elk_num_sources_from_inst(isa, inst);
1439
1440 if (elk_inst_dst_type(devinfo, inst) == type)
1441 return true;
1442
1443 if (num_sources >= 3) {
1444 return elk_inst_3src_a16_src_type(devinfo, inst) == type;
1445 } else if (num_sources == 2) {
1446 return elk_inst_src0_type(devinfo, inst) == type ||
1447 elk_inst_src1_type(devinfo, inst) == type;
1448 } else {
1449 return elk_inst_src0_type(devinfo, inst) == type;
1450 }
1451 }
1452
1453 #if MESA_DEBUG
1454 static __attribute__((__unused__)) int
elk_disassemble_imm(const struct elk_isa_info * isa,uint32_t dw3,uint32_t dw2,uint32_t dw1,uint32_t dw0)1455 elk_disassemble_imm(const struct elk_isa_info *isa,
1456 uint32_t dw3, uint32_t dw2, uint32_t dw1, uint32_t dw0)
1457 {
1458 elk_inst inst;
1459 inst.data[0] = (((uint64_t) dw1) << 32) | ((uint64_t) dw0);
1460 inst.data[1] = (((uint64_t) dw3) << 32) | ((uint64_t) dw2);
1461 return elk_disassemble_inst(stderr, isa, &inst, false, 0, NULL);
1462 }
1463 #endif
1464
1465 static void
write_label(FILE * file,const struct intel_device_info * devinfo,const struct elk_label * root_label,int offset,int jump)1466 write_label(FILE *file, const struct intel_device_info *devinfo,
1467 const struct elk_label *root_label,
1468 int offset, int jump)
1469 {
1470 if (root_label != NULL) {
1471 int to_bytes_scale = sizeof(elk_inst) / elk_jump_scale(devinfo);
1472 const struct elk_label *label =
1473 elk_find_label(root_label, offset + jump * to_bytes_scale);
1474 if (label != NULL) {
1475 format(file, " LABEL%d", label->number);
1476 }
1477 }
1478 }
1479
1480 static void
lsc_disassemble_ex_desc(const struct intel_device_info * devinfo,uint32_t imm_desc,uint32_t imm_ex_desc,FILE * file)1481 lsc_disassemble_ex_desc(const struct intel_device_info *devinfo,
1482 uint32_t imm_desc,
1483 uint32_t imm_ex_desc,
1484 FILE *file)
1485 {
1486 const unsigned addr_type = lsc_msg_desc_addr_type(devinfo, imm_desc);
1487 switch (addr_type) {
1488 case LSC_ADDR_SURFTYPE_FLAT:
1489 format(file, " base_offset %u ",
1490 lsc_flat_ex_desc_base_offset(devinfo, imm_ex_desc));
1491 break;
1492 case LSC_ADDR_SURFTYPE_BSS:
1493 case LSC_ADDR_SURFTYPE_SS:
1494 format(file, " surface_state_index %u ",
1495 lsc_bss_ex_desc_index(devinfo, imm_ex_desc));
1496 break;
1497 case LSC_ADDR_SURFTYPE_BTI:
1498 format(file, " BTI %u ",
1499 lsc_bti_ex_desc_index(devinfo, imm_ex_desc));
1500 format(file, " base_offset %u ",
1501 lsc_bti_ex_desc_base_offset(devinfo, imm_ex_desc));
1502 break;
1503 default:
1504 format(file, "unsupported address surface type %d", addr_type);
1505 break;
1506 }
1507 }
1508
1509 int
elk_disassemble_inst(FILE * file,const struct elk_isa_info * isa,const elk_inst * inst,bool is_compacted,int offset,const struct elk_label * root_label)1510 elk_disassemble_inst(FILE *file, const struct elk_isa_info *isa,
1511 const elk_inst *inst, bool is_compacted,
1512 int offset, const struct elk_label *root_label)
1513 {
1514 const struct intel_device_info *devinfo = isa->devinfo;
1515
1516 int err = 0;
1517 int space = 0;
1518
1519 const enum elk_opcode opcode = elk_inst_opcode(isa, inst);
1520 const struct elk_opcode_desc *desc = elk_opcode_desc(isa, opcode);
1521
1522 if (elk_inst_pred_control(devinfo, inst)) {
1523 string(file, "(");
1524 err |= control(file, "predicate inverse", pred_inv,
1525 elk_inst_pred_inv(devinfo, inst), NULL);
1526 format(file, "f%"PRIu64".%"PRIu64,
1527 devinfo->ver >= 7 ? elk_inst_flag_reg_nr(devinfo, inst) : 0,
1528 elk_inst_flag_subreg_nr(devinfo, inst));
1529 if (elk_inst_access_mode(devinfo, inst) == ELK_ALIGN_1) {
1530 err |= control(file, "predicate control align1", pred_ctrl_align1,
1531 elk_inst_pred_control(devinfo, inst), NULL);
1532 } else {
1533 err |= control(file, "predicate control align16", elk_pred_ctrl_align16,
1534 elk_inst_pred_control(devinfo, inst), NULL);
1535 }
1536 string(file, ") ");
1537 }
1538
1539 err |= print_opcode(file, isa, opcode);
1540
1541 if (!is_send(opcode))
1542 err |= control(file, "saturate", saturate, elk_inst_saturate(devinfo, inst),
1543 NULL);
1544
1545 err |= control(file, "debug control", debug_ctrl,
1546 elk_inst_debug_control(devinfo, inst), NULL);
1547
1548 if (opcode == ELK_OPCODE_MATH) {
1549 string(file, " ");
1550 err |= control(file, "function", math_function,
1551 elk_inst_math_function(devinfo, inst), NULL);
1552
1553 } else if (!is_send(opcode)) {
1554 err |= control(file, "conditional modifier", elk_conditional_modifier,
1555 elk_inst_cond_modifier(devinfo, inst), NULL);
1556
1557 /* If we're using the conditional modifier, print which flags reg is
1558 * used for it. Note that on gfx6+, the embedded-condition SEL and
1559 * control flow doesn't update flags.
1560 */
1561 if (elk_inst_cond_modifier(devinfo, inst) &&
1562 (devinfo->ver < 6 || (opcode != ELK_OPCODE_SEL &&
1563 opcode != ELK_OPCODE_CSEL &&
1564 opcode != ELK_OPCODE_IF &&
1565 opcode != ELK_OPCODE_WHILE))) {
1566 format(file, ".f%"PRIu64".%"PRIu64,
1567 devinfo->ver >= 7 ? elk_inst_flag_reg_nr(devinfo, inst) : 0,
1568 elk_inst_flag_subreg_nr(devinfo, inst));
1569 }
1570 }
1571
1572 if (opcode != ELK_OPCODE_NOP && opcode != ELK_OPCODE_NENOP) {
1573 string(file, "(");
1574 err |= control(file, "execution size", exec_size,
1575 elk_inst_exec_size(devinfo, inst), NULL);
1576 string(file, ")");
1577 }
1578
1579 if (opcode == ELK_OPCODE_SEND && devinfo->ver < 6)
1580 format(file, " %"PRIu64, elk_inst_base_mrf(devinfo, inst));
1581
1582 if (elk_has_uip(devinfo, opcode)) {
1583 /* Instructions that have UIP also have JIP. */
1584 pad(file, 16);
1585 string(file, "JIP: ");
1586 write_label(file, devinfo, root_label, offset, elk_inst_jip(devinfo, inst));
1587
1588 pad(file, 38);
1589 string(file, "UIP: ");
1590 write_label(file, devinfo, root_label, offset, elk_inst_uip(devinfo, inst));
1591 } else if (elk_has_jip(devinfo, opcode)) {
1592 int jip;
1593 if (devinfo->ver >= 7) {
1594 jip = elk_inst_jip(devinfo, inst);
1595 } else {
1596 jip = elk_inst_gfx6_jump_count(devinfo, inst);
1597 }
1598
1599 pad(file, 16);
1600 string(file, "JIP: ");
1601 write_label(file, devinfo, root_label, offset, jip);
1602 } else if (devinfo->ver < 6 && (opcode == ELK_OPCODE_BREAK ||
1603 opcode == ELK_OPCODE_CONTINUE ||
1604 opcode == ELK_OPCODE_ELSE)) {
1605 pad(file, 16);
1606 format(file, "Jump: %d", elk_inst_gfx4_jump_count(devinfo, inst));
1607 pad(file, 32);
1608 format(file, "Pop: %"PRIu64, elk_inst_gfx4_pop_count(devinfo, inst));
1609 } else if (devinfo->ver < 6 && (opcode == ELK_OPCODE_IF ||
1610 opcode == ELK_OPCODE_IFF ||
1611 opcode == ELK_OPCODE_HALT ||
1612 opcode == ELK_OPCODE_WHILE)) {
1613 pad(file, 16);
1614 format(file, "Jump: %d", elk_inst_gfx4_jump_count(devinfo, inst));
1615 } else if (devinfo->ver < 6 && opcode == ELK_OPCODE_ENDIF) {
1616 pad(file, 16);
1617 format(file, "Pop: %"PRIu64, elk_inst_gfx4_pop_count(devinfo, inst));
1618 } else if (opcode == ELK_OPCODE_JMPI) {
1619 pad(file, 16);
1620 err |= src1(file, isa, inst);
1621 } else if (desc && desc->nsrc == 3) {
1622 pad(file, 16);
1623 err |= dest_3src(file, devinfo, inst);
1624
1625 pad(file, 32);
1626 err |= src0_3src(file, devinfo, inst);
1627
1628 pad(file, 48);
1629 err |= src1_3src(file, devinfo, inst);
1630
1631 pad(file, 64);
1632 err |= src2_3src(file, devinfo, inst);
1633 } else if (desc) {
1634 if (desc->ndst > 0) {
1635 pad(file, 16);
1636 err |= dest(file, isa, inst);
1637 }
1638
1639 if (desc->nsrc > 0) {
1640 pad(file, 32);
1641 err |= src0(file, isa, inst);
1642 }
1643
1644 if (desc->nsrc > 1) {
1645 pad(file, 48);
1646 err |= src1(file, isa, inst);
1647 }
1648 }
1649
1650 if (is_send(opcode)) {
1651 enum elk_message_target sfid = elk_inst_sfid(devinfo, inst);
1652
1653 bool has_imm_desc = false, has_imm_ex_desc = false;
1654 uint32_t imm_desc = 0, imm_ex_desc = 0;
1655 {
1656 if (elk_inst_src1_reg_file(devinfo, inst) != ELK_IMMEDIATE_VALUE) {
1657 /* show the indirect descriptor source */
1658 pad(file, 48);
1659 err |= src1(file, isa, inst);
1660 pad(file, 64);
1661 } else {
1662 has_imm_desc = true;
1663 imm_desc = elk_inst_send_desc(devinfo, inst);
1664 pad(file, 48);
1665 }
1666
1667 /* Print message descriptor as immediate source */
1668 fprintf(file, "0x%08"PRIx64, inst->data[1] >> 32);
1669 }
1670
1671 newline(file);
1672 pad(file, 16);
1673 space = 0;
1674
1675 fprintf(file, " ");
1676 err |= control(file, "SFID", devinfo->ver >= 6 ? gfx6_sfid : gfx4_sfid,
1677 sfid, &space);
1678 string(file, " MsgDesc:");
1679
1680 if (!has_imm_desc) {
1681 format(file, " indirect");
1682 } else {
1683 bool unsupported = false;
1684 switch (sfid) {
1685 case ELK_SFID_MATH:
1686 err |= control(file, "math function", math_function,
1687 elk_inst_math_msg_function(devinfo, inst), &space);
1688 err |= control(file, "math saturate", math_saturate,
1689 elk_inst_math_msg_saturate(devinfo, inst), &space);
1690 err |= control(file, "math signed", math_signed,
1691 elk_inst_math_msg_signed_int(devinfo, inst), &space);
1692 err |= control(file, "math scalar", math_scalar,
1693 elk_inst_math_msg_data_type(devinfo, inst), &space);
1694 err |= control(file, "math precision", math_precision,
1695 elk_inst_math_msg_precision(devinfo, inst), &space);
1696 break;
1697 case ELK_SFID_SAMPLER:
1698 if (devinfo->ver >= 5) {
1699 err |= control(file, "sampler message", gfx5_sampler_msg_type,
1700 elk_sampler_desc_msg_type(devinfo, imm_desc),
1701 &space);
1702 err |= control(file, "sampler simd mode", gfx5_sampler_simd_mode,
1703 elk_sampler_desc_simd_mode(devinfo, imm_desc),
1704 &space);
1705 if (devinfo->ver >= 8 &&
1706 elk_sampler_desc_return_format(devinfo, imm_desc)) {
1707 string(file, " HP");
1708 }
1709 format(file, " Surface = %u Sampler = %u",
1710 elk_sampler_desc_binding_table_index(devinfo, imm_desc),
1711 elk_sampler_desc_sampler(devinfo, imm_desc));
1712 } else {
1713 format(file, " (bti %u, sampler %u, msg_type %u, ",
1714 elk_sampler_desc_binding_table_index(devinfo, imm_desc),
1715 elk_sampler_desc_sampler(devinfo, imm_desc),
1716 elk_sampler_desc_msg_type(devinfo, imm_desc));
1717 if (devinfo->verx10 != 45) {
1718 err |= control(file, "sampler target format",
1719 sampler_target_format,
1720 elk_sampler_desc_return_format(devinfo, imm_desc),
1721 NULL);
1722 }
1723 string(file, ")");
1724 }
1725 break;
1726 case GFX6_SFID_DATAPORT_SAMPLER_CACHE:
1727 case GFX6_SFID_DATAPORT_CONSTANT_CACHE:
1728 /* aka ELK_SFID_DATAPORT_READ on Gfx4-5 */
1729 if (devinfo->ver >= 6) {
1730 format(file, " (bti %u, msg_ctrl %u, msg_type %u, write_commit %u)",
1731 elk_dp_desc_binding_table_index(devinfo, imm_desc),
1732 elk_dp_desc_msg_control(devinfo, imm_desc),
1733 elk_dp_desc_msg_type(devinfo, imm_desc),
1734 devinfo->ver >= 7 ? 0u :
1735 elk_dp_write_desc_write_commit(devinfo, imm_desc));
1736 } else {
1737 bool is_965 = devinfo->verx10 == 40;
1738 err |= control(file, "DP read message type",
1739 is_965 ? gfx4_dp_read_port_msg_type :
1740 g45_dp_read_port_msg_type,
1741 elk_dp_read_desc_msg_type(devinfo, imm_desc),
1742 &space);
1743
1744 format(file, " MsgCtrl = 0x%u",
1745 elk_dp_read_desc_msg_control(devinfo, imm_desc));
1746
1747 format(file, " Surface = %u",
1748 elk_dp_desc_binding_table_index(devinfo, imm_desc));
1749 }
1750 break;
1751
1752 case GFX6_SFID_DATAPORT_RENDER_CACHE: {
1753 /* aka ELK_SFID_DATAPORT_WRITE on Gfx4-5 */
1754 unsigned msg_type = elk_fb_write_desc_msg_type(devinfo, imm_desc);
1755
1756 err |= control(file, "DP rc message type",
1757 dp_rc_msg_type(devinfo), msg_type, &space);
1758
1759 bool is_rt_write = msg_type ==
1760 (devinfo->ver >= 6 ? GFX6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE
1761 : ELK_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE);
1762
1763 if (is_rt_write) {
1764 err |= control(file, "RT message type", m_rt_write_subtype,
1765 elk_inst_rt_message_type(devinfo, inst), &space);
1766 if (devinfo->ver >= 6 && elk_inst_rt_slot_group(devinfo, inst))
1767 string(file, " Hi");
1768 if (elk_fb_write_desc_last_render_target(devinfo, imm_desc))
1769 string(file, " LastRT");
1770 if (devinfo->ver < 7 &&
1771 elk_fb_write_desc_write_commit(devinfo, imm_desc))
1772 string(file, " WriteCommit");
1773 } else {
1774 format(file, " MsgCtrl = 0x%u",
1775 elk_fb_write_desc_msg_control(devinfo, imm_desc));
1776 }
1777
1778 format(file, " Surface = %u",
1779 elk_fb_desc_binding_table_index(devinfo, imm_desc));
1780 break;
1781 }
1782
1783 case ELK_SFID_URB: {
1784 unsigned urb_opcode = elk_inst_urb_opcode(devinfo, inst);
1785
1786 format(file, " offset %"PRIu64, elk_inst_urb_global_offset(devinfo, inst));
1787
1788 space = 1;
1789
1790 err |= control(file, "urb opcode",
1791 devinfo->ver >= 7 ? gfx7_urb_opcode
1792 : gfx5_urb_opcode,
1793 urb_opcode, &space);
1794
1795 if (devinfo->ver >= 7 &&
1796 elk_inst_urb_per_slot_offset(devinfo, inst)) {
1797 string(file, " per-slot");
1798 }
1799
1800 if (urb_opcode == GFX8_URB_OPCODE_SIMD8_WRITE ||
1801 urb_opcode == GFX8_URB_OPCODE_SIMD8_READ) {
1802 if (elk_inst_urb_channel_mask_present(devinfo, inst))
1803 string(file, " masked");
1804 } else {
1805 err |= control(file, "urb swizzle", urb_swizzle,
1806 elk_inst_urb_swizzle_control(devinfo, inst),
1807 &space);
1808 }
1809
1810 if (devinfo->ver < 7) {
1811 err |= control(file, "urb allocate", urb_allocate,
1812 elk_inst_urb_allocate(devinfo, inst), &space);
1813 err |= control(file, "urb used", urb_used,
1814 elk_inst_urb_used(devinfo, inst), &space);
1815 }
1816 if (devinfo->ver < 8) {
1817 err |= control(file, "urb complete", urb_complete,
1818 elk_inst_urb_complete(devinfo, inst), &space);
1819 }
1820 break;
1821 }
1822 case ELK_SFID_THREAD_SPAWNER:
1823 break;
1824
1825 case ELK_SFID_MESSAGE_GATEWAY:
1826 format(file, " (%s)",
1827 gfx7_gateway_subfuncid[elk_inst_gateway_subfuncid(devinfo, inst)]);
1828 break;
1829
1830 case GFX7_SFID_DATAPORT_DATA_CACHE:
1831 if (devinfo->ver >= 7) {
1832 format(file, " (");
1833 space = 0;
1834
1835 err |= control(file, "DP DC0 message type",
1836 dp_dc0_msg_type_gfx7,
1837 elk_dp_desc_msg_type(devinfo, imm_desc), &space);
1838
1839 format(file, ", bti %u, ",
1840 elk_dp_desc_binding_table_index(devinfo, imm_desc));
1841
1842 switch (elk_inst_dp_msg_type(devinfo, inst)) {
1843 case GFX7_DATAPORT_DC_UNTYPED_ATOMIC_OP:
1844 control(file, "atomic op", aop,
1845 elk_dp_desc_msg_control(devinfo, imm_desc) & 0xf,
1846 &space);
1847 break;
1848 case GFX7_DATAPORT_DC_OWORD_BLOCK_READ:
1849 case GFX7_DATAPORT_DC_OWORD_BLOCK_WRITE: {
1850 unsigned msg_ctrl = elk_dp_desc_msg_control(devinfo, imm_desc);
1851 assert(dp_oword_block_rw[msg_ctrl & 7]);
1852 format(file, "owords = %s, aligned = %d",
1853 dp_oword_block_rw[msg_ctrl & 7], (msg_ctrl >> 3) & 3);
1854 break;
1855 }
1856 default:
1857 format(file, "%u",
1858 elk_dp_desc_msg_control(devinfo, imm_desc));
1859 }
1860 format(file, ")");
1861 } else {
1862 unsupported = true;
1863 }
1864 break;
1865
1866 case HSW_SFID_DATAPORT_DATA_CACHE_1: {
1867 if (devinfo->ver >= 7) {
1868 format(file, " (");
1869 space = 0;
1870
1871 unsigned msg_ctrl = elk_dp_desc_msg_control(devinfo, imm_desc);
1872
1873 err |= control(file, "DP DC1 message type",
1874 dp_dc1_msg_type_hsw,
1875 elk_dp_desc_msg_type(devinfo, imm_desc), &space);
1876
1877 format(file, ", Surface = %u, ",
1878 elk_dp_desc_binding_table_index(devinfo, imm_desc));
1879
1880 switch (elk_inst_dp_msg_type(devinfo, inst)) {
1881 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP:
1882 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP:
1883 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP:
1884 format(file, "SIMD%d,", (msg_ctrl & (1 << 4)) ? 8 : 16);
1885 FALLTHROUGH;
1886 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2:
1887 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2:
1888 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2:
1889 case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_ATOMIC_OP:
1890 control(file, "atomic op", aop, msg_ctrl & 0xf, &space);
1891 break;
1892 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ:
1893 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE:
1894 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ:
1895 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE:
1896 case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_WRITE:
1897 case GFX8_DATAPORT_DC_PORT1_A64_UNTYPED_SURFACE_READ: {
1898 static const char *simd_modes[] = { "4x2", "16", "8" };
1899 format(file, "SIMD%s, Mask = 0x%x",
1900 simd_modes[msg_ctrl >> 4], msg_ctrl & 0xf);
1901 break;
1902 }
1903 case GFX8_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_WRITE:
1904 case GFX8_DATAPORT_DC_PORT1_A64_OWORD_BLOCK_READ:
1905 assert(dp_oword_block_rw[msg_ctrl & 7]);
1906 format(file, "owords = %s, aligned = %d",
1907 dp_oword_block_rw[msg_ctrl & 7], (msg_ctrl >> 3) & 3);
1908 break;
1909 default:
1910 format(file, "0x%x", msg_ctrl);
1911 }
1912 format(file, ")");
1913 } else {
1914 unsupported = true;
1915 }
1916 break;
1917 }
1918
1919 case GFX7_SFID_PIXEL_INTERPOLATOR:
1920 if (devinfo->ver >= 7) {
1921 format(file, " (%s, %s, 0x%02"PRIx64")",
1922 elk_inst_pi_nopersp(devinfo, inst) ? "linear" : "persp",
1923 pixel_interpolator_msg_types[elk_inst_pi_message_type(devinfo, inst)],
1924 elk_inst_pi_message_data(devinfo, inst));
1925 } else {
1926 unsupported = true;
1927 }
1928 break;
1929
1930 default:
1931 unsupported = true;
1932 break;
1933 }
1934
1935 if (unsupported)
1936 format(file, "unsupported shared function ID %d", sfid);
1937
1938 if (space)
1939 string(file, " ");
1940 }
1941 if (has_imm_desc)
1942 format(file, " mlen %u", elk_message_desc_mlen(devinfo, imm_desc));
1943 if (has_imm_ex_desc) {
1944 format(file, " ex_mlen %u",
1945 elk_message_ex_desc_ex_mlen(devinfo, imm_ex_desc));
1946 }
1947 if (has_imm_desc)
1948 format(file, " rlen %u", elk_message_desc_rlen(devinfo, imm_desc));
1949 }
1950 pad(file, 64);
1951 if (opcode != ELK_OPCODE_NOP && opcode != ELK_OPCODE_NENOP) {
1952 string(file, "{");
1953 space = 1;
1954 err |= control(file, "access mode", access_mode,
1955 elk_inst_access_mode(devinfo, inst), &space);
1956 if (devinfo->ver >= 6) {
1957 err |= control(file, "write enable control", wectrl,
1958 elk_inst_mask_control(devinfo, inst), &space);
1959 } else {
1960 err |= control(file, "mask control", mask_ctrl,
1961 elk_inst_mask_control(devinfo, inst), &space);
1962 }
1963
1964 err |= control(file, "dependency control", dep_ctrl,
1965 ((elk_inst_no_dd_check(devinfo, inst) << 1) |
1966 elk_inst_no_dd_clear(devinfo, inst)), &space);
1967
1968 if (devinfo->ver >= 6)
1969 err |= qtr_ctrl(file, devinfo, inst);
1970 else {
1971 if (elk_inst_qtr_control(devinfo, inst) == ELK_COMPRESSION_COMPRESSED &&
1972 desc && desc->ndst > 0 &&
1973 elk_inst_dst_reg_file(devinfo, inst) == ELK_MESSAGE_REGISTER_FILE &&
1974 elk_inst_dst_da_reg_nr(devinfo, inst) & ELK_MRF_COMPR4) {
1975 format(file, " compr4");
1976 } else {
1977 err |= control(file, "compression control", compr_ctrl,
1978 elk_inst_qtr_control(devinfo, inst), &space);
1979 }
1980 }
1981
1982 err |= control(file, "compaction", cmpt_ctrl, is_compacted, &space);
1983 err |= control(file, "thread control", thread_ctrl,
1984 elk_inst_thread_control(devinfo, inst),
1985 &space);
1986 if (has_branch_ctrl(devinfo, opcode)) {
1987 err |= control(file, "branch ctrl", branch_ctrl,
1988 elk_inst_branch_control(devinfo, inst), &space);
1989 } else if (devinfo->ver >= 6) {
1990 err |= control(file, "acc write control", accwr,
1991 elk_inst_acc_wr_control(devinfo, inst), &space);
1992 }
1993 if (is_send(opcode))
1994 err |= control(file, "end of thread", end_of_thread,
1995 elk_inst_eot(devinfo, inst), &space);
1996 if (space)
1997 string(file, " ");
1998 string(file, "}");
1999 }
2000 string(file, ";");
2001 newline(file);
2002 return err;
2003 }
2004
2005 int
elk_disassemble_find_end(const struct elk_isa_info * isa,const void * assembly,int start)2006 elk_disassemble_find_end(const struct elk_isa_info *isa,
2007 const void *assembly, int start)
2008 {
2009 const struct intel_device_info *devinfo = isa->devinfo;
2010 int offset = start;
2011
2012 /* This loop exits when send-with-EOT or when opcode is 0 */
2013 while (true) {
2014 const elk_inst *insn = assembly + offset;
2015
2016 if (elk_inst_cmpt_control(devinfo, insn)) {
2017 offset += 8;
2018 } else {
2019 offset += 16;
2020 }
2021
2022 /* Simplistic, but efficient way to terminate disasm */
2023 uint32_t opcode = elk_inst_opcode(isa, insn);
2024 if (opcode == 0 || (is_send(opcode) && elk_inst_eot(devinfo, insn))) {
2025 break;
2026 }
2027 }
2028
2029 return offset;
2030 }
2031
2032 void
elk_disassemble_with_errors(const struct elk_isa_info * isa,const void * assembly,int start,FILE * out)2033 elk_disassemble_with_errors(const struct elk_isa_info *isa,
2034 const void *assembly, int start, FILE *out)
2035 {
2036 int end = elk_disassemble_find_end(isa, assembly, start);
2037
2038 /* Make a dummy disasm structure that elk_validate_instructions
2039 * can work from.
2040 */
2041 struct elk_disasm_info *elk_disasm_info = elk_disasm_initialize(isa, NULL);
2042 elk_disasm_new_inst_group(elk_disasm_info, start);
2043 elk_disasm_new_inst_group(elk_disasm_info, end);
2044
2045 elk_validate_instructions(isa, assembly, start, end, elk_disasm_info);
2046
2047 void *mem_ctx = ralloc_context(NULL);
2048 const struct elk_label *root_label =
2049 elk_label_assembly(isa, assembly, start, end, mem_ctx);
2050
2051 foreach_list_typed(struct inst_group, group, link,
2052 &elk_disasm_info->group_list) {
2053 struct exec_node *next_node = exec_node_get_next(&group->link);
2054 if (exec_node_is_tail_sentinel(next_node))
2055 break;
2056
2057 struct inst_group *next =
2058 exec_node_data(struct inst_group, next_node, link);
2059
2060 int start_offset = group->offset;
2061 int end_offset = next->offset;
2062
2063 elk_disassemble(isa, assembly, start_offset, end_offset,
2064 root_label, out);
2065
2066 if (group->error) {
2067 fputs(group->error, out);
2068 }
2069 }
2070
2071 ralloc_free(mem_ctx);
2072 ralloc_free(elk_disasm_info);
2073 }
2074