intel/fs: Retype dest to match value in read[First]Invocation
[mesa.git] / src / intel / compiler / brw_disasm.c
1 /*
2 * Copyright © 2008 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdarg.h>
26
27 #include "brw_eu_defines.h"
28 #include "brw_inst.h"
29 #include "brw_shader.h"
30 #include "brw_reg.h"
31 #include "brw_inst.h"
32 #include "brw_eu.h"
33 #include "util/half_float.h"
34
35 static bool
36 has_jip(const struct gen_device_info *devinfo, enum opcode opcode)
37 {
38 if (devinfo->gen < 6)
39 return false;
40
41 return opcode == BRW_OPCODE_IF ||
42 opcode == BRW_OPCODE_ELSE ||
43 opcode == BRW_OPCODE_ENDIF ||
44 opcode == BRW_OPCODE_WHILE ||
45 opcode == BRW_OPCODE_BREAK ||
46 opcode == BRW_OPCODE_CONTINUE ||
47 opcode == BRW_OPCODE_HALT;
48 }
49
50 static bool
51 has_uip(const struct gen_device_info *devinfo, enum opcode opcode)
52 {
53 if (devinfo->gen < 6)
54 return false;
55
56 return (devinfo->gen >= 7 && opcode == BRW_OPCODE_IF) ||
57 (devinfo->gen >= 8 && opcode == BRW_OPCODE_ELSE) ||
58 opcode == BRW_OPCODE_BREAK ||
59 opcode == BRW_OPCODE_CONTINUE ||
60 opcode == BRW_OPCODE_HALT;
61 }
62
63 static bool
64 has_branch_ctrl(const struct gen_device_info *devinfo, enum opcode opcode)
65 {
66 if (devinfo->gen < 8)
67 return false;
68
69 return opcode == BRW_OPCODE_IF ||
70 opcode == BRW_OPCODE_ELSE;
71 /* opcode == BRW_OPCODE_GOTO; */
72 }
73
74 static bool
75 is_logic_instruction(unsigned opcode)
76 {
77 return opcode == BRW_OPCODE_AND ||
78 opcode == BRW_OPCODE_NOT ||
79 opcode == BRW_OPCODE_OR ||
80 opcode == BRW_OPCODE_XOR;
81 }
82
83 const char *const conditional_modifier[16] = {
84 [BRW_CONDITIONAL_NONE] = "",
85 [BRW_CONDITIONAL_Z] = ".z",
86 [BRW_CONDITIONAL_NZ] = ".nz",
87 [BRW_CONDITIONAL_G] = ".g",
88 [BRW_CONDITIONAL_GE] = ".ge",
89 [BRW_CONDITIONAL_L] = ".l",
90 [BRW_CONDITIONAL_LE] = ".le",
91 [BRW_CONDITIONAL_R] = ".r",
92 [BRW_CONDITIONAL_O] = ".o",
93 [BRW_CONDITIONAL_U] = ".u",
94 };
95
96 static const char *const m_negate[2] = {
97 [0] = "",
98 [1] = "-",
99 };
100
101 static const char *const _abs[2] = {
102 [0] = "",
103 [1] = "(abs)",
104 };
105
106 static const char *const m_bitnot[2] = { "", "~" };
107
108 static const char *const vert_stride[16] = {
109 [0] = "0",
110 [1] = "1",
111 [2] = "2",
112 [3] = "4",
113 [4] = "8",
114 [5] = "16",
115 [6] = "32",
116 [15] = "VxH",
117 };
118
119 static const char *const width[8] = {
120 [0] = "1",
121 [1] = "2",
122 [2] = "4",
123 [3] = "8",
124 [4] = "16",
125 };
126
127 static const char *const horiz_stride[4] = {
128 [0] = "0",
129 [1] = "1",
130 [2] = "2",
131 [3] = "4"
132 };
133
134 static const char *const chan_sel[4] = {
135 [0] = "x",
136 [1] = "y",
137 [2] = "z",
138 [3] = "w",
139 };
140
141 static const char *const debug_ctrl[2] = {
142 [0] = "",
143 [1] = ".breakpoint"
144 };
145
146 static const char *const saturate[2] = {
147 [0] = "",
148 [1] = ".sat"
149 };
150
151 static const char *const cmpt_ctrl[2] = {
152 [0] = "",
153 [1] = "compacted"
154 };
155
156 static const char *const accwr[2] = {
157 [0] = "",
158 [1] = "AccWrEnable"
159 };
160
161 static const char *const branch_ctrl[2] = {
162 [0] = "",
163 [1] = "BranchCtrl"
164 };
165
166 static const char *const wectrl[2] = {
167 [0] = "",
168 [1] = "WE_all"
169 };
170
171 static const char *const exec_size[8] = {
172 [0] = "1",
173 [1] = "2",
174 [2] = "4",
175 [3] = "8",
176 [4] = "16",
177 [5] = "32"
178 };
179
180 static const char *const pred_inv[2] = {
181 [0] = "+",
182 [1] = "-"
183 };
184
185 const char *const pred_ctrl_align16[16] = {
186 [1] = "",
187 [2] = ".x",
188 [3] = ".y",
189 [4] = ".z",
190 [5] = ".w",
191 [6] = ".any4h",
192 [7] = ".all4h",
193 };
194
195 static const char *const pred_ctrl_align1[16] = {
196 [BRW_PREDICATE_NORMAL] = "",
197 [BRW_PREDICATE_ALIGN1_ANYV] = ".anyv",
198 [BRW_PREDICATE_ALIGN1_ALLV] = ".allv",
199 [BRW_PREDICATE_ALIGN1_ANY2H] = ".any2h",
200 [BRW_PREDICATE_ALIGN1_ALL2H] = ".all2h",
201 [BRW_PREDICATE_ALIGN1_ANY4H] = ".any4h",
202 [BRW_PREDICATE_ALIGN1_ALL4H] = ".all4h",
203 [BRW_PREDICATE_ALIGN1_ANY8H] = ".any8h",
204 [BRW_PREDICATE_ALIGN1_ALL8H] = ".all8h",
205 [BRW_PREDICATE_ALIGN1_ANY16H] = ".any16h",
206 [BRW_PREDICATE_ALIGN1_ALL16H] = ".all16h",
207 [BRW_PREDICATE_ALIGN1_ANY32H] = ".any32h",
208 [BRW_PREDICATE_ALIGN1_ALL32H] = ".all32h",
209 };
210
211 static const char *const thread_ctrl[4] = {
212 [BRW_THREAD_NORMAL] = "",
213 [BRW_THREAD_ATOMIC] = "atomic",
214 [BRW_THREAD_SWITCH] = "switch",
215 };
216
217 static const char *const compr_ctrl[4] = {
218 [0] = "",
219 [1] = "sechalf",
220 [2] = "compr",
221 [3] = "compr4",
222 };
223
224 static const char *const dep_ctrl[4] = {
225 [0] = "",
226 [1] = "NoDDClr",
227 [2] = "NoDDChk",
228 [3] = "NoDDClr,NoDDChk",
229 };
230
231 static const char *const mask_ctrl[4] = {
232 [0] = "",
233 [1] = "nomask",
234 };
235
236 static const char *const access_mode[2] = {
237 [0] = "align1",
238 [1] = "align16",
239 };
240
241 static const char *const reg_file[4] = {
242 [0] = "A",
243 [1] = "g",
244 [2] = "m",
245 [3] = "imm",
246 };
247
248 static const char *const writemask[16] = {
249 [0x0] = ".",
250 [0x1] = ".x",
251 [0x2] = ".y",
252 [0x3] = ".xy",
253 [0x4] = ".z",
254 [0x5] = ".xz",
255 [0x6] = ".yz",
256 [0x7] = ".xyz",
257 [0x8] = ".w",
258 [0x9] = ".xw",
259 [0xa] = ".yw",
260 [0xb] = ".xyw",
261 [0xc] = ".zw",
262 [0xd] = ".xzw",
263 [0xe] = ".yzw",
264 [0xf] = "",
265 };
266
267 static const char *const end_of_thread[2] = {
268 [0] = "",
269 [1] = "EOT"
270 };
271
272 /* SFIDs on Gen4-5 */
273 static const char *const gen4_sfid[16] = {
274 [BRW_SFID_NULL] = "null",
275 [BRW_SFID_MATH] = "math",
276 [BRW_SFID_SAMPLER] = "sampler",
277 [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
278 [BRW_SFID_DATAPORT_READ] = "read",
279 [BRW_SFID_DATAPORT_WRITE] = "write",
280 [BRW_SFID_URB] = "urb",
281 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner",
282 [BRW_SFID_VME] = "vme",
283 };
284
285 static const char *const gen6_sfid[16] = {
286 [BRW_SFID_NULL] = "null",
287 [BRW_SFID_MATH] = "math",
288 [BRW_SFID_SAMPLER] = "sampler",
289 [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
290 [BRW_SFID_URB] = "urb",
291 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner",
292 [GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "sampler",
293 [GEN6_SFID_DATAPORT_RENDER_CACHE] = "render",
294 [GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "const",
295 [GEN7_SFID_DATAPORT_DATA_CACHE] = "data",
296 [GEN7_SFID_PIXEL_INTERPOLATOR] = "pixel interp",
297 [HSW_SFID_DATAPORT_DATA_CACHE_1] = "dp data 1",
298 [HSW_SFID_CRE] = "cre",
299 };
300
301 static const char *const gen7_gateway_subfuncid[8] = {
302 [BRW_MESSAGE_GATEWAY_SFID_OPEN_GATEWAY] = "open",
303 [BRW_MESSAGE_GATEWAY_SFID_CLOSE_GATEWAY] = "close",
304 [BRW_MESSAGE_GATEWAY_SFID_FORWARD_MSG] = "forward msg",
305 [BRW_MESSAGE_GATEWAY_SFID_GET_TIMESTAMP] = "get timestamp",
306 [BRW_MESSAGE_GATEWAY_SFID_BARRIER_MSG] = "barrier msg",
307 [BRW_MESSAGE_GATEWAY_SFID_UPDATE_GATEWAY_STATE] = "update state",
308 [BRW_MESSAGE_GATEWAY_SFID_MMIO_READ_WRITE] = "mmio read/write",
309 };
310
311 static const char *const gen4_dp_read_port_msg_type[4] = {
312 [0b00] = "OWord Block Read",
313 [0b01] = "OWord Dual Block Read",
314 [0b10] = "Media Block Read",
315 [0b11] = "DWord Scattered Read",
316 };
317
318 static const char *const g45_dp_read_port_msg_type[8] = {
319 [0b000] = "OWord Block Read",
320 [0b010] = "OWord Dual Block Read",
321 [0b100] = "Media Block Read",
322 [0b110] = "DWord Scattered Read",
323 [0b001] = "Render Target UNORM Read",
324 [0b011] = "AVC Loop Filter Read",
325 };
326
327 static const char *const dp_write_port_msg_type[8] = {
328 [0b000] = "OWord block write",
329 [0b001] = "OWord dual block write",
330 [0b010] = "media block write",
331 [0b011] = "DWord scattered write",
332 [0b100] = "RT write",
333 [0b101] = "streamed VB write",
334 [0b110] = "RT UNORM write", /* G45+ */
335 [0b111] = "flush render cache",
336 };
337
338 static const char *const dp_rc_msg_type_gen6[16] = {
339 [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
340 [GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
341 [GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
342 [GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read",
343 [GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] =
344 "OWORD unaligned block read",
345 [GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read",
346 [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write",
347 [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write",
348 [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] =
349 "OWORD dual block write",
350 [GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write",
351 [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] =
352 "DWORD scattered write",
353 [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write",
354 [GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write",
355 [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORM write",
356 };
357
358 static const char *const dp_rc_msg_type_gen7[16] = {
359 [GEN7_DATAPORT_RC_MEDIA_BLOCK_READ] = "media block read",
360 [GEN7_DATAPORT_RC_TYPED_SURFACE_READ] = "typed surface read",
361 [GEN7_DATAPORT_RC_TYPED_ATOMIC_OP] = "typed atomic op",
362 [GEN7_DATAPORT_RC_MEMORY_FENCE] = "memory fence",
363 [GEN7_DATAPORT_RC_MEDIA_BLOCK_WRITE] = "media block write",
364 [GEN7_DATAPORT_RC_RENDER_TARGET_WRITE] = "RT write",
365 [GEN7_DATAPORT_RC_TYPED_SURFACE_WRITE] = "typed surface write"
366 };
367
368 static const char *const dp_rc_msg_type_gen9[16] = {
369 [GEN9_DATAPORT_RC_RENDER_TARGET_WRITE] = "RT write",
370 [GEN9_DATAPORT_RC_RENDER_TARGET_READ] = "RT read"
371 };
372
373 static const char *const *
374 dp_rc_msg_type(const struct gen_device_info *devinfo)
375 {
376 return (devinfo->gen >= 9 ? dp_rc_msg_type_gen9 :
377 devinfo->gen >= 7 ? dp_rc_msg_type_gen7 :
378 devinfo->gen >= 6 ? dp_rc_msg_type_gen6 :
379 dp_write_port_msg_type);
380 }
381
382 static const char *const m_rt_write_subtype[] = {
383 [0b000] = "SIMD16",
384 [0b001] = "SIMD16/RepData",
385 [0b010] = "SIMD8/DualSrcLow",
386 [0b011] = "SIMD8/DualSrcHigh",
387 [0b100] = "SIMD8",
388 [0b101] = "SIMD8/ImageWrite", /* Gen6+ */
389 [0b111] = "SIMD16/RepData-111", /* no idea how this is different than 1 */
390 };
391
392 static const char *const dp_dc0_msg_type_gen7[16] = {
393 [GEN7_DATAPORT_DC_OWORD_BLOCK_READ] = "DC OWORD block read",
394 [GEN7_DATAPORT_DC_UNALIGNED_OWORD_BLOCK_READ] =
395 "DC unaligned OWORD block read",
396 [GEN7_DATAPORT_DC_OWORD_DUAL_BLOCK_READ] = "DC OWORD dual block read",
397 [GEN7_DATAPORT_DC_DWORD_SCATTERED_READ] = "DC DWORD scattered read",
398 [GEN7_DATAPORT_DC_BYTE_SCATTERED_READ] = "DC byte scattered read",
399 [GEN7_DATAPORT_DC_UNTYPED_SURFACE_READ] = "DC untyped surface read",
400 [GEN7_DATAPORT_DC_UNTYPED_ATOMIC_OP] = "DC untyped atomic",
401 [GEN7_DATAPORT_DC_MEMORY_FENCE] = "DC mfence",
402 [GEN7_DATAPORT_DC_OWORD_BLOCK_WRITE] = "DC OWORD block write",
403 [GEN7_DATAPORT_DC_OWORD_DUAL_BLOCK_WRITE] = "DC OWORD dual block write",
404 [GEN7_DATAPORT_DC_DWORD_SCATTERED_WRITE] = "DC DWORD scatterd write",
405 [GEN7_DATAPORT_DC_BYTE_SCATTERED_WRITE] = "DC byte scattered write",
406 [GEN7_DATAPORT_DC_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
407 };
408
409 static const char *const dp_dc1_msg_type_hsw[16] = {
410 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ] = "untyped surface read",
411 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP] = "DC untyped atomic op",
412 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2] =
413 "DC untyped 4x2 atomic op",
414 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_READ] = "DC media block read",
415 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ] = "DC typed surface read",
416 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP] = "DC typed atomic",
417 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2] = "DC typed 4x2 atomic op",
418 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
419 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_WRITE] = "DC media block write",
420 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP] = "DC atomic counter op",
421 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2] =
422 "DC 4x2 atomic counter op",
423 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE] = "DC typed surface write",
424 };
425
426 static const char *const aop[16] = {
427 [BRW_AOP_AND] = "and",
428 [BRW_AOP_OR] = "or",
429 [BRW_AOP_XOR] = "xor",
430 [BRW_AOP_MOV] = "mov",
431 [BRW_AOP_INC] = "inc",
432 [BRW_AOP_DEC] = "dec",
433 [BRW_AOP_ADD] = "add",
434 [BRW_AOP_SUB] = "sub",
435 [BRW_AOP_REVSUB] = "revsub",
436 [BRW_AOP_IMAX] = "imax",
437 [BRW_AOP_IMIN] = "imin",
438 [BRW_AOP_UMAX] = "umax",
439 [BRW_AOP_UMIN] = "umin",
440 [BRW_AOP_CMPWR] = "cmpwr",
441 [BRW_AOP_PREDEC] = "predec",
442 };
443
444 static const char * const pixel_interpolator_msg_types[4] = {
445 [GEN7_PIXEL_INTERPOLATOR_LOC_SHARED_OFFSET] = "per_message_offset",
446 [GEN7_PIXEL_INTERPOLATOR_LOC_SAMPLE] = "sample_position",
447 [GEN7_PIXEL_INTERPOLATOR_LOC_CENTROID] = "centroid",
448 [GEN7_PIXEL_INTERPOLATOR_LOC_PER_SLOT_OFFSET] = "per_slot_offset",
449 };
450
451 static const char *const math_function[16] = {
452 [BRW_MATH_FUNCTION_INV] = "inv",
453 [BRW_MATH_FUNCTION_LOG] = "log",
454 [BRW_MATH_FUNCTION_EXP] = "exp",
455 [BRW_MATH_FUNCTION_SQRT] = "sqrt",
456 [BRW_MATH_FUNCTION_RSQ] = "rsq",
457 [BRW_MATH_FUNCTION_SIN] = "sin",
458 [BRW_MATH_FUNCTION_COS] = "cos",
459 [BRW_MATH_FUNCTION_SINCOS] = "sincos",
460 [BRW_MATH_FUNCTION_FDIV] = "fdiv",
461 [BRW_MATH_FUNCTION_POW] = "pow",
462 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
463 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
464 [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
465 [GEN8_MATH_FUNCTION_INVM] = "invm",
466 [GEN8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
467 };
468
469 static const char *const math_saturate[2] = {
470 [0] = "",
471 [1] = "sat"
472 };
473
474 static const char *const math_signed[2] = {
475 [0] = "",
476 [1] = "signed"
477 };
478
479 static const char *const math_scalar[2] = {
480 [0] = "",
481 [1] = "scalar"
482 };
483
484 static const char *const math_precision[2] = {
485 [0] = "",
486 [1] = "partial_precision"
487 };
488
489 static const char *const gen5_urb_opcode[] = {
490 [0] = "urb_write",
491 [1] = "ff_sync",
492 };
493
494 static const char *const gen7_urb_opcode[] = {
495 [BRW_URB_OPCODE_WRITE_HWORD] = "write HWord",
496 [BRW_URB_OPCODE_WRITE_OWORD] = "write OWord",
497 [BRW_URB_OPCODE_READ_HWORD] = "read HWord",
498 [BRW_URB_OPCODE_READ_OWORD] = "read OWord",
499 [GEN7_URB_OPCODE_ATOMIC_MOV] = "atomic mov", /* Gen7+ */
500 [GEN7_URB_OPCODE_ATOMIC_INC] = "atomic inc", /* Gen7+ */
501 [GEN8_URB_OPCODE_ATOMIC_ADD] = "atomic add", /* Gen8+ */
502 [GEN8_URB_OPCODE_SIMD8_WRITE] = "SIMD8 write", /* Gen8+ */
503 [GEN8_URB_OPCODE_SIMD8_READ] = "SIMD8 read", /* Gen8+ */
504 /* [9-15] - reserved */
505 };
506
507 static const char *const urb_swizzle[4] = {
508 [BRW_URB_SWIZZLE_NONE] = "",
509 [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
510 [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose",
511 };
512
513 static const char *const urb_allocate[2] = {
514 [0] = "",
515 [1] = "allocate"
516 };
517
518 static const char *const urb_used[2] = {
519 [0] = "",
520 [1] = "used"
521 };
522
523 static const char *const urb_complete[2] = {
524 [0] = "",
525 [1] = "complete"
526 };
527
528 static const char *const gen5_sampler_msg_type[] = {
529 [GEN5_SAMPLER_MESSAGE_SAMPLE] = "sample",
530 [GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS] = "sample_b",
531 [GEN5_SAMPLER_MESSAGE_SAMPLE_LOD] = "sample_l",
532 [GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE] = "sample_c",
533 [GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS] = "sample_d",
534 [GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE] = "sample_b_c",
535 [GEN5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE] = "sample_l_c",
536 [GEN5_SAMPLER_MESSAGE_SAMPLE_LD] = "ld",
537 [GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4] = "gather4",
538 [GEN5_SAMPLER_MESSAGE_LOD] = "lod",
539 [GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO] = "resinfo",
540 [GEN6_SAMPLER_MESSAGE_SAMPLE_SAMPLEINFO] = "sampleinfo",
541 [GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_C] = "gather4_c",
542 [GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO] = "gather4_po",
543 [GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO_C] = "gather4_po_c",
544 [HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE] = "sample_d_c",
545 [GEN9_SAMPLER_MESSAGE_SAMPLE_LZ] = "sample_lz",
546 [GEN9_SAMPLER_MESSAGE_SAMPLE_C_LZ] = "sample_c_lz",
547 [GEN9_SAMPLER_MESSAGE_SAMPLE_LD_LZ] = "ld_lz",
548 [GEN9_SAMPLER_MESSAGE_SAMPLE_LD2DMS_W] = "ld2dms_w",
549 [GEN7_SAMPLER_MESSAGE_SAMPLE_LD_MCS] = "ld_mcs",
550 [GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS] = "ld2dms",
551 [GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DSS] = "ld2dss",
552 };
553
554 static const char *const gen5_sampler_simd_mode[4] = {
555 [BRW_SAMPLER_SIMD_MODE_SIMD4X2] = "SIMD4x2",
556 [BRW_SAMPLER_SIMD_MODE_SIMD8] = "SIMD8",
557 [BRW_SAMPLER_SIMD_MODE_SIMD16] = "SIMD16",
558 [BRW_SAMPLER_SIMD_MODE_SIMD32_64] = "SIMD32/64",
559 };
560
561 static const char *const sampler_target_format[4] = {
562 [0] = "F",
563 [2] = "UD",
564 [3] = "D"
565 };
566
567
568 static int column;
569
570 static int
571 string(FILE *file, const char *string)
572 {
573 fputs(string, file);
574 column += strlen(string);
575 return 0;
576 }
577
578 static int
579 format(FILE *f, const char *format, ...) PRINTFLIKE(2, 3);
580
581 static int
582 format(FILE *f, const char *format, ...)
583 {
584 char buf[1024];
585 va_list args;
586 va_start(args, format);
587
588 vsnprintf(buf, sizeof(buf) - 1, format, args);
589 va_end(args);
590 string(f, buf);
591 return 0;
592 }
593
594 static int
595 newline(FILE *f)
596 {
597 putc('\n', f);
598 column = 0;
599 return 0;
600 }
601
602 static int
603 pad(FILE *f, int c)
604 {
605 do
606 string(f, " ");
607 while (column < c);
608 return 0;
609 }
610
611 static int
612 control(FILE *file, const char *name, const char *const ctrl[],
613 unsigned id, int *space)
614 {
615 if (!ctrl[id]) {
616 fprintf(file, "*** invalid %s value %d ", name, id);
617 return 1;
618 }
619 if (ctrl[id][0]) {
620 if (space && *space)
621 string(file, " ");
622 string(file, ctrl[id]);
623 if (space)
624 *space = 1;
625 }
626 return 0;
627 }
628
629 static int
630 print_opcode(FILE *file, const struct gen_device_info *devinfo,
631 enum opcode id)
632 {
633 const struct opcode_desc *desc = brw_opcode_desc(devinfo, id);
634 if (!desc) {
635 format(file, "*** invalid opcode value %d ", id);
636 return 1;
637 }
638 string(file, desc->name);
639 return 0;
640 }
641
642 static int
643 reg(FILE *file, unsigned _reg_file, unsigned _reg_nr)
644 {
645 int err = 0;
646
647 /* Clear the Compr4 instruction compression bit. */
648 if (_reg_file == BRW_MESSAGE_REGISTER_FILE)
649 _reg_nr &= ~BRW_MRF_COMPR4;
650
651 if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
652 switch (_reg_nr & 0xf0) {
653 case BRW_ARF_NULL:
654 string(file, "null");
655 break;
656 case BRW_ARF_ADDRESS:
657 format(file, "a%d", _reg_nr & 0x0f);
658 break;
659 case BRW_ARF_ACCUMULATOR:
660 format(file, "acc%d", _reg_nr & 0x0f);
661 break;
662 case BRW_ARF_FLAG:
663 format(file, "f%d", _reg_nr & 0x0f);
664 break;
665 case BRW_ARF_MASK:
666 format(file, "mask%d", _reg_nr & 0x0f);
667 break;
668 case BRW_ARF_MASK_STACK:
669 format(file, "msd%d", _reg_nr & 0x0f);
670 break;
671 case BRW_ARF_STATE:
672 format(file, "sr%d", _reg_nr & 0x0f);
673 break;
674 case BRW_ARF_CONTROL:
675 format(file, "cr%d", _reg_nr & 0x0f);
676 break;
677 case BRW_ARF_NOTIFICATION_COUNT:
678 format(file, "n%d", _reg_nr & 0x0f);
679 break;
680 case BRW_ARF_IP:
681 string(file, "ip");
682 return -1;
683 break;
684 case BRW_ARF_TDR:
685 format(file, "tdr0");
686 return -1;
687 case BRW_ARF_TIMESTAMP:
688 format(file, "tm%d", _reg_nr & 0x0f);
689 break;
690 default:
691 format(file, "ARF%d", _reg_nr);
692 break;
693 }
694 } else {
695 err |= control(file, "src reg file", reg_file, _reg_file, NULL);
696 format(file, "%d", _reg_nr);
697 }
698 return err;
699 }
700
701 static int
702 dest(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
703 {
704 enum brw_reg_type type = brw_inst_dst_type(devinfo, inst);
705 unsigned elem_size = brw_reg_type_to_size(type);
706 int err = 0;
707
708 if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
709 if (brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
710 err |= reg(file, brw_inst_dst_reg_file(devinfo, inst),
711 brw_inst_dst_da_reg_nr(devinfo, inst));
712 if (err == -1)
713 return 0;
714 if (brw_inst_dst_da1_subreg_nr(devinfo, inst))
715 format(file, ".%"PRIu64, brw_inst_dst_da1_subreg_nr(devinfo, inst) /
716 elem_size);
717 string(file, "<");
718 err |= control(file, "horiz stride", horiz_stride,
719 brw_inst_dst_hstride(devinfo, inst), NULL);
720 string(file, ">");
721 string(file, brw_reg_type_to_letters(type));
722 } else {
723 string(file, "g[a0");
724 if (brw_inst_dst_ia_subreg_nr(devinfo, inst))
725 format(file, ".%"PRIu64, brw_inst_dst_ia_subreg_nr(devinfo, inst) /
726 elem_size);
727 if (brw_inst_dst_ia1_addr_imm(devinfo, inst))
728 format(file, " %d", brw_inst_dst_ia1_addr_imm(devinfo, inst));
729 string(file, "]<");
730 err |= control(file, "horiz stride", horiz_stride,
731 brw_inst_dst_hstride(devinfo, inst), NULL);
732 string(file, ">");
733 string(file, brw_reg_type_to_letters(type));
734 }
735 } else {
736 if (brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
737 err |= reg(file, brw_inst_dst_reg_file(devinfo, inst),
738 brw_inst_dst_da_reg_nr(devinfo, inst));
739 if (err == -1)
740 return 0;
741 if (brw_inst_dst_da16_subreg_nr(devinfo, inst))
742 format(file, ".%u", 16 / elem_size);
743 string(file, "<1>");
744 err |= control(file, "writemask", writemask,
745 brw_inst_da16_writemask(devinfo, inst), NULL);
746 string(file, brw_reg_type_to_letters(type));
747 } else {
748 err = 1;
749 string(file, "Indirect align16 address mode not supported");
750 }
751 }
752
753 return 0;
754 }
755
756 static int
757 dest_3src(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
758 {
759 bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
760 int err = 0;
761 uint32_t reg_file;
762 unsigned subreg_nr;
763 enum brw_reg_type type;
764
765 if (is_align1 && brw_inst_3src_a1_dst_reg_file(devinfo, inst))
766 reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
767 else if (devinfo->gen == 6 && brw_inst_3src_a16_dst_reg_file(devinfo, inst))
768 reg_file = BRW_MESSAGE_REGISTER_FILE;
769 else
770 reg_file = BRW_GENERAL_REGISTER_FILE;
771
772 err |= reg(file, reg_file, brw_inst_3src_dst_reg_nr(devinfo, inst));
773 if (err == -1)
774 return 0;
775
776 if (is_align1) {
777 type = brw_inst_3src_a1_dst_type(devinfo, inst);
778 subreg_nr = brw_inst_3src_a1_dst_subreg_nr(devinfo, inst);
779 } else {
780 type = brw_inst_3src_a16_dst_type(devinfo, inst);
781 subreg_nr = brw_inst_3src_a16_dst_subreg_nr(devinfo, inst) * 4;
782 }
783 subreg_nr /= brw_reg_type_to_size(type);
784
785 if (subreg_nr)
786 format(file, ".%u", subreg_nr);
787 string(file, "<1>");
788
789 if (!is_align1) {
790 err |= control(file, "writemask", writemask,
791 brw_inst_3src_a16_dst_writemask(devinfo, inst), NULL);
792 }
793 string(file, brw_reg_type_to_letters(type));
794
795 return 0;
796 }
797
798 static int
799 src_align1_region(FILE *file,
800 unsigned _vert_stride, unsigned _width,
801 unsigned _horiz_stride)
802 {
803 int err = 0;
804 string(file, "<");
805 err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
806 string(file, ",");
807 err |= control(file, "width", width, _width, NULL);
808 string(file, ",");
809 err |= control(file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
810 string(file, ">");
811 return err;
812 }
813
814 static int
815 src_da1(FILE *file,
816 const struct gen_device_info *devinfo,
817 unsigned opcode,
818 enum brw_reg_type type, unsigned _reg_file,
819 unsigned _vert_stride, unsigned _width, unsigned _horiz_stride,
820 unsigned reg_num, unsigned sub_reg_num, unsigned __abs,
821 unsigned _negate)
822 {
823 int err = 0;
824
825 if (devinfo->gen >= 8 && is_logic_instruction(opcode))
826 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
827 else
828 err |= control(file, "negate", m_negate, _negate, NULL);
829
830 err |= control(file, "abs", _abs, __abs, NULL);
831
832 err |= reg(file, _reg_file, reg_num);
833 if (err == -1)
834 return 0;
835 if (sub_reg_num) {
836 unsigned elem_size = brw_reg_type_to_size(type);
837 format(file, ".%d", sub_reg_num / elem_size); /* use formal style like spec */
838 }
839 src_align1_region(file, _vert_stride, _width, _horiz_stride);
840 string(file, brw_reg_type_to_letters(type));
841 return err;
842 }
843
844 static int
845 src_ia1(FILE *file,
846 const struct gen_device_info *devinfo,
847 unsigned opcode,
848 enum brw_reg_type type,
849 unsigned _reg_file,
850 int _addr_imm,
851 unsigned _addr_subreg_nr,
852 unsigned _negate,
853 unsigned __abs,
854 unsigned _horiz_stride, unsigned _width, unsigned _vert_stride)
855 {
856 int err = 0;
857
858 if (devinfo->gen >= 8 && is_logic_instruction(opcode))
859 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
860 else
861 err |= control(file, "negate", m_negate, _negate, NULL);
862
863 err |= control(file, "abs", _abs, __abs, NULL);
864
865 string(file, "g[a0");
866 if (_addr_subreg_nr)
867 format(file, ".%d", _addr_subreg_nr);
868 if (_addr_imm)
869 format(file, " %d", _addr_imm);
870 string(file, "]");
871 src_align1_region(file, _vert_stride, _width, _horiz_stride);
872 string(file, brw_reg_type_to_letters(type));
873 return err;
874 }
875
876 static int
877 src_swizzle(FILE *file, unsigned swiz)
878 {
879 unsigned x = BRW_GET_SWZ(swiz, BRW_CHANNEL_X);
880 unsigned y = BRW_GET_SWZ(swiz, BRW_CHANNEL_Y);
881 unsigned z = BRW_GET_SWZ(swiz, BRW_CHANNEL_Z);
882 unsigned w = BRW_GET_SWZ(swiz, BRW_CHANNEL_W);
883 int err = 0;
884
885 if (x == y && x == z && x == w) {
886 string(file, ".");
887 err |= control(file, "channel select", chan_sel, x, NULL);
888 } else if (swiz != BRW_SWIZZLE_XYZW) {
889 string(file, ".");
890 err |= control(file, "channel select", chan_sel, x, NULL);
891 err |= control(file, "channel select", chan_sel, y, NULL);
892 err |= control(file, "channel select", chan_sel, z, NULL);
893 err |= control(file, "channel select", chan_sel, w, NULL);
894 }
895 return err;
896 }
897
898 static int
899 src_da16(FILE *file,
900 const struct gen_device_info *devinfo,
901 unsigned opcode,
902 enum brw_reg_type type,
903 unsigned _reg_file,
904 unsigned _vert_stride,
905 unsigned _reg_nr,
906 unsigned _subreg_nr,
907 unsigned __abs,
908 unsigned _negate,
909 unsigned swz_x, unsigned swz_y, unsigned swz_z, unsigned swz_w)
910 {
911 int err = 0;
912
913 if (devinfo->gen >= 8 && is_logic_instruction(opcode))
914 err |= control(file, "bitnot", m_bitnot, _negate, NULL);
915 else
916 err |= control(file, "negate", m_negate, _negate, NULL);
917
918 err |= control(file, "abs", _abs, __abs, NULL);
919
920 err |= reg(file, _reg_file, _reg_nr);
921 if (err == -1)
922 return 0;
923 if (_subreg_nr) {
924 unsigned elem_size = brw_reg_type_to_size(type);
925
926 /* bit4 for subreg number byte addressing. Make this same meaning as
927 in da1 case, so output looks consistent. */
928 format(file, ".%d", 16 / elem_size);
929 }
930 string(file, "<");
931 err |= control(file, "vert stride", vert_stride, _vert_stride, NULL);
932 string(file, ">");
933 err |= src_swizzle(file, BRW_SWIZZLE4(swz_x, swz_y, swz_z, swz_w));
934 string(file, brw_reg_type_to_letters(type));
935 return err;
936 }
937
938 static enum brw_vertical_stride
939 vstride_from_align1_3src_vstride(enum gen10_align1_3src_vertical_stride vstride)
940 {
941 switch (vstride) {
942 case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_0: return BRW_VERTICAL_STRIDE_0;
943 case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_2: return BRW_VERTICAL_STRIDE_2;
944 case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_4: return BRW_VERTICAL_STRIDE_4;
945 case BRW_ALIGN1_3SRC_VERTICAL_STRIDE_8: return BRW_VERTICAL_STRIDE_8;
946 default:
947 unreachable("not reached");
948 }
949 }
950
951 static enum brw_horizontal_stride
952 hstride_from_align1_3src_hstride(enum gen10_align1_3src_src_horizontal_stride hstride)
953 {
954 switch (hstride) {
955 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return BRW_HORIZONTAL_STRIDE_0;
956 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return BRW_HORIZONTAL_STRIDE_1;
957 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return BRW_HORIZONTAL_STRIDE_2;
958 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return BRW_HORIZONTAL_STRIDE_4;
959 default:
960 unreachable("not reached");
961 }
962 }
963
964 static enum brw_vertical_stride
965 vstride_from_align1_3src_hstride(enum gen10_align1_3src_src_horizontal_stride hstride)
966 {
967 switch (hstride) {
968 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_0: return BRW_VERTICAL_STRIDE_0;
969 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_1: return BRW_VERTICAL_STRIDE_1;
970 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_2: return BRW_VERTICAL_STRIDE_2;
971 case BRW_ALIGN1_3SRC_SRC_HORIZONTAL_STRIDE_4: return BRW_VERTICAL_STRIDE_4;
972 default:
973 unreachable("not reached");
974 }
975 }
976
977 /* From "GEN10 Regioning Rules for Align1 Ternary Operations" in the
978 * "Register Region Restrictions" documentation
979 */
980 static enum brw_width
981 implied_width(enum brw_vertical_stride _vert_stride,
982 enum brw_horizontal_stride _horiz_stride)
983 {
984 /* "1. Width is 1 when Vertical and Horizontal Strides are both zero." */
985 if (_vert_stride == BRW_VERTICAL_STRIDE_0 &&
986 _horiz_stride == BRW_HORIZONTAL_STRIDE_0) {
987 return BRW_WIDTH_1;
988
989 /* "2. Width is equal to vertical stride when Horizontal Stride is zero." */
990 } else if (_horiz_stride == BRW_HORIZONTAL_STRIDE_0) {
991 switch (_vert_stride) {
992 case BRW_VERTICAL_STRIDE_2: return BRW_WIDTH_2;
993 case BRW_VERTICAL_STRIDE_4: return BRW_WIDTH_4;
994 case BRW_VERTICAL_STRIDE_8: return BRW_WIDTH_8;
995 case BRW_VERTICAL_STRIDE_0:
996 default:
997 unreachable("not reached");
998 }
999
1000 } else {
1001 /* FINISHME: Implement these: */
1002
1003 /* "3. Width is equal to Vertical Stride/Horizontal Stride when both
1004 * Strides are non-zero.
1005 *
1006 * 4. Vertical Stride must not be zero if Horizontal Stride is non-zero.
1007 * This implies Vertical Stride is always greater than Horizontal
1008 * Stride."
1009 *
1010 * Given these statements and the knowledge that the stride and width
1011 * values are encoded in logarithmic form, we can perform the division
1012 * by just subtracting.
1013 */
1014 return _vert_stride - _horiz_stride;
1015 }
1016 }
1017
1018 static int
1019 src0_3src(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1020 {
1021 int err = 0;
1022 unsigned reg_nr, subreg_nr;
1023 enum brw_reg_file _file;
1024 enum brw_reg_type type;
1025 enum brw_vertical_stride _vert_stride;
1026 enum brw_width _width;
1027 enum brw_horizontal_stride _horiz_stride;
1028 bool is_scalar_region;
1029 bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1030
1031 if (is_align1) {
1032 if (brw_inst_3src_a1_src0_reg_file(devinfo, inst) ==
1033 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1034 _file = BRW_GENERAL_REGISTER_FILE;
1035 reg_nr = brw_inst_3src_src0_reg_nr(devinfo, inst);
1036 subreg_nr = brw_inst_3src_a1_src0_subreg_nr(devinfo, inst);
1037 type = brw_inst_3src_a1_src0_type(devinfo, inst);
1038 } else {
1039 _file = BRW_IMMEDIATE_VALUE;
1040 uint16_t imm_val = brw_inst_3src_a1_src0_imm(devinfo, inst);
1041 enum brw_reg_type type = brw_inst_3src_a1_src0_type(devinfo, inst);
1042
1043 if (type == BRW_REGISTER_TYPE_W) {
1044 format(file, "%dW", imm_val);
1045 } else if (type == BRW_REGISTER_TYPE_UW) {
1046 format(file, "0x%04xUW", imm_val);
1047 } else if (type == BRW_REGISTER_TYPE_HF) {
1048 format(file, "%-gF", _mesa_half_to_float(imm_val));
1049 }
1050 return 0;
1051 }
1052
1053 _vert_stride = vstride_from_align1_3src_vstride(
1054 brw_inst_3src_a1_src0_vstride(devinfo, inst));
1055 _horiz_stride = hstride_from_align1_3src_hstride(
1056 brw_inst_3src_a1_src0_hstride(devinfo, inst));
1057 _width = implied_width(_vert_stride, _horiz_stride);
1058 } else {
1059 _file = BRW_GENERAL_REGISTER_FILE;
1060 reg_nr = brw_inst_3src_src0_reg_nr(devinfo, inst);
1061 subreg_nr = brw_inst_3src_a16_src0_subreg_nr(devinfo, inst) * 4;
1062 type = brw_inst_3src_a16_src_type(devinfo, inst);
1063
1064 if (brw_inst_3src_a16_src0_rep_ctrl(devinfo, inst)) {
1065 _vert_stride = BRW_VERTICAL_STRIDE_0;
1066 _width = BRW_WIDTH_1;
1067 _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1068 } else {
1069 _vert_stride = BRW_VERTICAL_STRIDE_4;
1070 _width = BRW_WIDTH_4;
1071 _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1072 }
1073 }
1074 is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1075 _width == BRW_WIDTH_1 &&
1076 _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1077
1078 subreg_nr /= brw_reg_type_to_size(type);
1079
1080 err |= control(file, "negate", m_negate,
1081 brw_inst_3src_src0_negate(devinfo, inst), NULL);
1082 err |= control(file, "abs", _abs, brw_inst_3src_src0_abs(devinfo, inst), NULL);
1083
1084 err |= reg(file, _file, reg_nr);
1085 if (err == -1)
1086 return 0;
1087 if (subreg_nr || is_scalar_region)
1088 format(file, ".%d", subreg_nr);
1089 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1090 if (!is_scalar_region && !is_align1)
1091 err |= src_swizzle(file, brw_inst_3src_a16_src0_swizzle(devinfo, inst));
1092 string(file, brw_reg_type_to_letters(type));
1093 return err;
1094 }
1095
1096 static int
1097 src1_3src(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1098 {
1099 int err = 0;
1100 unsigned reg_nr, subreg_nr;
1101 enum brw_reg_file _file;
1102 enum brw_reg_type type;
1103 enum brw_vertical_stride _vert_stride;
1104 enum brw_width _width;
1105 enum brw_horizontal_stride _horiz_stride;
1106 bool is_scalar_region;
1107 bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1108
1109 if (is_align1) {
1110 if (brw_inst_3src_a1_src1_reg_file(devinfo, inst) ==
1111 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1112 _file = BRW_GENERAL_REGISTER_FILE;
1113 } else {
1114 _file = BRW_ARCHITECTURE_REGISTER_FILE;
1115 }
1116
1117 reg_nr = brw_inst_3src_src1_reg_nr(devinfo, inst);
1118 subreg_nr = brw_inst_3src_a1_src1_subreg_nr(devinfo, inst);
1119 type = brw_inst_3src_a1_src1_type(devinfo, inst);
1120
1121 _vert_stride = vstride_from_align1_3src_vstride(
1122 brw_inst_3src_a1_src1_vstride(devinfo, inst));
1123 _horiz_stride = hstride_from_align1_3src_hstride(
1124 brw_inst_3src_a1_src1_hstride(devinfo, inst));
1125 _width = implied_width(_vert_stride, _horiz_stride);
1126 } else {
1127 _file = BRW_GENERAL_REGISTER_FILE;
1128 reg_nr = brw_inst_3src_src1_reg_nr(devinfo, inst);
1129 subreg_nr = brw_inst_3src_a16_src1_subreg_nr(devinfo, inst) * 4;
1130 type = brw_inst_3src_a16_src_type(devinfo, inst);
1131
1132 if (brw_inst_3src_a16_src1_rep_ctrl(devinfo, inst)) {
1133 _vert_stride = BRW_VERTICAL_STRIDE_0;
1134 _width = BRW_WIDTH_1;
1135 _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1136 } else {
1137 _vert_stride = BRW_VERTICAL_STRIDE_4;
1138 _width = BRW_WIDTH_4;
1139 _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1140 }
1141 }
1142 is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1143 _width == BRW_WIDTH_1 &&
1144 _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1145
1146 subreg_nr /= brw_reg_type_to_size(type);
1147
1148 err |= control(file, "negate", m_negate,
1149 brw_inst_3src_src1_negate(devinfo, inst), NULL);
1150 err |= control(file, "abs", _abs, brw_inst_3src_src1_abs(devinfo, inst), NULL);
1151
1152 err |= reg(file, _file, reg_nr);
1153 if (err == -1)
1154 return 0;
1155 if (subreg_nr || is_scalar_region)
1156 format(file, ".%d", subreg_nr);
1157 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1158 if (!is_scalar_region && !is_align1)
1159 err |= src_swizzle(file, brw_inst_3src_a16_src1_swizzle(devinfo, inst));
1160 string(file, brw_reg_type_to_letters(type));
1161 return err;
1162 }
1163
1164 static int
1165 src2_3src(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1166 {
1167 int err = 0;
1168 unsigned reg_nr, subreg_nr;
1169 enum brw_reg_file _file;
1170 enum brw_reg_type type;
1171 enum brw_vertical_stride _vert_stride;
1172 enum brw_width _width;
1173 enum brw_horizontal_stride _horiz_stride;
1174 bool is_scalar_region;
1175 bool is_align1 = brw_inst_3src_access_mode(devinfo, inst) == BRW_ALIGN_1;
1176
1177 if (is_align1) {
1178 if (brw_inst_3src_a1_src2_reg_file(devinfo, inst) ==
1179 BRW_ALIGN1_3SRC_GENERAL_REGISTER_FILE) {
1180 _file = BRW_GENERAL_REGISTER_FILE;
1181 reg_nr = brw_inst_3src_src2_reg_nr(devinfo, inst);
1182 subreg_nr = brw_inst_3src_a1_src2_subreg_nr(devinfo, inst);
1183 type = brw_inst_3src_a1_src2_type(devinfo, inst);
1184 } else {
1185 _file = BRW_IMMEDIATE_VALUE;
1186 uint16_t imm_val = brw_inst_3src_a1_src2_imm(devinfo, inst);
1187 enum brw_reg_type type = brw_inst_3src_a1_src2_type(devinfo, inst);
1188
1189 if (type == BRW_REGISTER_TYPE_W) {
1190 format(file, "%dW", imm_val);
1191 } else if (type == BRW_REGISTER_TYPE_UW) {
1192 format(file, "0x%04xUW", imm_val);
1193 } else if (type == BRW_REGISTER_TYPE_HF) {
1194 format(file, "%-gF", _mesa_half_to_float(imm_val));
1195 }
1196 return 0;
1197 }
1198
1199 /* FINISHME: No vertical stride on src2. Is using the hstride in place
1200 * correct? Doesn't seem like it, since there's hstride=1 but
1201 * no vstride=1.
1202 */
1203 _vert_stride = vstride_from_align1_3src_hstride(
1204 brw_inst_3src_a1_src2_hstride(devinfo, inst));
1205 _horiz_stride = hstride_from_align1_3src_hstride(
1206 brw_inst_3src_a1_src2_hstride(devinfo, inst));
1207 _width = implied_width(_vert_stride, _horiz_stride);
1208 } else {
1209 _file = BRW_GENERAL_REGISTER_FILE;
1210 reg_nr = brw_inst_3src_src2_reg_nr(devinfo, inst);
1211 subreg_nr = brw_inst_3src_a16_src2_subreg_nr(devinfo, inst) * 4;
1212 type = brw_inst_3src_a16_src_type(devinfo, inst);
1213
1214 if (brw_inst_3src_a16_src2_rep_ctrl(devinfo, inst)) {
1215 _vert_stride = BRW_VERTICAL_STRIDE_0;
1216 _width = BRW_WIDTH_1;
1217 _horiz_stride = BRW_HORIZONTAL_STRIDE_0;
1218 } else {
1219 _vert_stride = BRW_VERTICAL_STRIDE_4;
1220 _width = BRW_WIDTH_4;
1221 _horiz_stride = BRW_HORIZONTAL_STRIDE_1;
1222 }
1223 }
1224 is_scalar_region = _vert_stride == BRW_VERTICAL_STRIDE_0 &&
1225 _width == BRW_WIDTH_1 &&
1226 _horiz_stride == BRW_HORIZONTAL_STRIDE_0;
1227
1228 subreg_nr /= brw_reg_type_to_size(type);
1229
1230 err |= control(file, "negate", m_negate,
1231 brw_inst_3src_src2_negate(devinfo, inst), NULL);
1232 err |= control(file, "abs", _abs, brw_inst_3src_src2_abs(devinfo, inst), NULL);
1233
1234 err |= reg(file, _file, reg_nr);
1235 if (err == -1)
1236 return 0;
1237 if (subreg_nr || is_scalar_region)
1238 format(file, ".%d", subreg_nr);
1239 src_align1_region(file, _vert_stride, _width, _horiz_stride);
1240 if (!is_scalar_region && !is_align1)
1241 err |= src_swizzle(file, brw_inst_3src_a16_src2_swizzle(devinfo, inst));
1242 string(file, brw_reg_type_to_letters(type));
1243 return err;
1244 }
1245
1246 static int
1247 imm(FILE *file, const struct gen_device_info *devinfo, enum brw_reg_type type,
1248 const brw_inst *inst)
1249 {
1250 switch (type) {
1251 case BRW_REGISTER_TYPE_UQ:
1252 format(file, "0x%016lxUQ", brw_inst_imm_uq(devinfo, inst));
1253 break;
1254 case BRW_REGISTER_TYPE_Q:
1255 format(file, "%ldQ", brw_inst_imm_uq(devinfo, inst));
1256 break;
1257 case BRW_REGISTER_TYPE_UD:
1258 format(file, "0x%08xUD", brw_inst_imm_ud(devinfo, inst));
1259 break;
1260 case BRW_REGISTER_TYPE_D:
1261 format(file, "%dD", brw_inst_imm_d(devinfo, inst));
1262 break;
1263 case BRW_REGISTER_TYPE_UW:
1264 format(file, "0x%04xUW", (uint16_t) brw_inst_imm_ud(devinfo, inst));
1265 break;
1266 case BRW_REGISTER_TYPE_W:
1267 format(file, "%dW", (int16_t) brw_inst_imm_d(devinfo, inst));
1268 break;
1269 case BRW_REGISTER_TYPE_UV:
1270 format(file, "0x%08xUV", brw_inst_imm_ud(devinfo, inst));
1271 break;
1272 case BRW_REGISTER_TYPE_VF:
1273 format(file, "[%-gF, %-gF, %-gF, %-gF]VF",
1274 brw_vf_to_float(brw_inst_imm_ud(devinfo, inst)),
1275 brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 8),
1276 brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 16),
1277 brw_vf_to_float(brw_inst_imm_ud(devinfo, inst) >> 24));
1278 break;
1279 case BRW_REGISTER_TYPE_V:
1280 format(file, "0x%08xV", brw_inst_imm_ud(devinfo, inst));
1281 break;
1282 case BRW_REGISTER_TYPE_F:
1283 format(file, "%-gF", brw_inst_imm_f(devinfo, inst));
1284 break;
1285 case BRW_REGISTER_TYPE_DF:
1286 format(file, "%-gDF", brw_inst_imm_df(devinfo, inst));
1287 break;
1288 case BRW_REGISTER_TYPE_HF:
1289 string(file, "Half Float IMM");
1290 break;
1291 case BRW_REGISTER_TYPE_UB:
1292 case BRW_REGISTER_TYPE_B:
1293 format(file, "*** invalid immediate type %d ", type);
1294 }
1295 return 0;
1296 }
1297
1298 static int
1299 src0(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1300 {
1301 if (brw_inst_src0_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE) {
1302 return imm(file, devinfo, brw_inst_src0_type(devinfo, inst), inst);
1303 } else if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1304 if (brw_inst_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1305 return src_da1(file,
1306 devinfo,
1307 brw_inst_opcode(devinfo, inst),
1308 brw_inst_src0_type(devinfo, inst),
1309 brw_inst_src0_reg_file(devinfo, inst),
1310 brw_inst_src0_vstride(devinfo, inst),
1311 brw_inst_src0_width(devinfo, inst),
1312 brw_inst_src0_hstride(devinfo, inst),
1313 brw_inst_src0_da_reg_nr(devinfo, inst),
1314 brw_inst_src0_da1_subreg_nr(devinfo, inst),
1315 brw_inst_src0_abs(devinfo, inst),
1316 brw_inst_src0_negate(devinfo, inst));
1317 } else {
1318 return src_ia1(file,
1319 devinfo,
1320 brw_inst_opcode(devinfo, inst),
1321 brw_inst_src0_type(devinfo, inst),
1322 brw_inst_src0_reg_file(devinfo, inst),
1323 brw_inst_src0_ia1_addr_imm(devinfo, inst),
1324 brw_inst_src0_ia_subreg_nr(devinfo, inst),
1325 brw_inst_src0_negate(devinfo, inst),
1326 brw_inst_src0_abs(devinfo, inst),
1327 brw_inst_src0_hstride(devinfo, inst),
1328 brw_inst_src0_width(devinfo, inst),
1329 brw_inst_src0_vstride(devinfo, inst));
1330 }
1331 } else {
1332 if (brw_inst_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1333 return src_da16(file,
1334 devinfo,
1335 brw_inst_opcode(devinfo, inst),
1336 brw_inst_src0_type(devinfo, inst),
1337 brw_inst_src0_reg_file(devinfo, inst),
1338 brw_inst_src0_vstride(devinfo, inst),
1339 brw_inst_src0_da_reg_nr(devinfo, inst),
1340 brw_inst_src0_da16_subreg_nr(devinfo, inst),
1341 brw_inst_src0_abs(devinfo, inst),
1342 brw_inst_src0_negate(devinfo, inst),
1343 brw_inst_src0_da16_swiz_x(devinfo, inst),
1344 brw_inst_src0_da16_swiz_y(devinfo, inst),
1345 brw_inst_src0_da16_swiz_z(devinfo, inst),
1346 brw_inst_src0_da16_swiz_w(devinfo, inst));
1347 } else {
1348 string(file, "Indirect align16 address mode not supported");
1349 return 1;
1350 }
1351 }
1352 }
1353
1354 static int
1355 src1(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1356 {
1357 if (brw_inst_src1_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE) {
1358 return imm(file, devinfo, brw_inst_src1_type(devinfo, inst), inst);
1359 } else if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1360 if (brw_inst_src1_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1361 return src_da1(file,
1362 devinfo,
1363 brw_inst_opcode(devinfo, inst),
1364 brw_inst_src1_type(devinfo, inst),
1365 brw_inst_src1_reg_file(devinfo, inst),
1366 brw_inst_src1_vstride(devinfo, inst),
1367 brw_inst_src1_width(devinfo, inst),
1368 brw_inst_src1_hstride(devinfo, inst),
1369 brw_inst_src1_da_reg_nr(devinfo, inst),
1370 brw_inst_src1_da1_subreg_nr(devinfo, inst),
1371 brw_inst_src1_abs(devinfo, inst),
1372 brw_inst_src1_negate(devinfo, inst));
1373 } else {
1374 return src_ia1(file,
1375 devinfo,
1376 brw_inst_opcode(devinfo, inst),
1377 brw_inst_src1_type(devinfo, inst),
1378 brw_inst_src1_reg_file(devinfo, inst),
1379 brw_inst_src1_ia1_addr_imm(devinfo, inst),
1380 brw_inst_src1_ia_subreg_nr(devinfo, inst),
1381 brw_inst_src1_negate(devinfo, inst),
1382 brw_inst_src1_abs(devinfo, inst),
1383 brw_inst_src1_hstride(devinfo, inst),
1384 brw_inst_src1_width(devinfo, inst),
1385 brw_inst_src1_vstride(devinfo, inst));
1386 }
1387 } else {
1388 if (brw_inst_src1_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
1389 return src_da16(file,
1390 devinfo,
1391 brw_inst_opcode(devinfo, inst),
1392 brw_inst_src1_type(devinfo, inst),
1393 brw_inst_src1_reg_file(devinfo, inst),
1394 brw_inst_src1_vstride(devinfo, inst),
1395 brw_inst_src1_da_reg_nr(devinfo, inst),
1396 brw_inst_src1_da16_subreg_nr(devinfo, inst),
1397 brw_inst_src1_abs(devinfo, inst),
1398 brw_inst_src1_negate(devinfo, inst),
1399 brw_inst_src1_da16_swiz_x(devinfo, inst),
1400 brw_inst_src1_da16_swiz_y(devinfo, inst),
1401 brw_inst_src1_da16_swiz_z(devinfo, inst),
1402 brw_inst_src1_da16_swiz_w(devinfo, inst));
1403 } else {
1404 string(file, "Indirect align16 address mode not supported");
1405 return 1;
1406 }
1407 }
1408 }
1409
1410 static int
1411 qtr_ctrl(FILE *file, const struct gen_device_info *devinfo, const brw_inst *inst)
1412 {
1413 int qtr_ctl = brw_inst_qtr_control(devinfo, inst);
1414 int exec_size = 1 << brw_inst_exec_size(devinfo, inst);
1415 const unsigned nib_ctl = devinfo->gen < 7 ? 0 :
1416 brw_inst_nib_control(devinfo, inst);
1417
1418 if (exec_size < 8 || nib_ctl) {
1419 format(file, " %dN", qtr_ctl * 2 + nib_ctl + 1);
1420 } else if (exec_size == 8) {
1421 switch (qtr_ctl) {
1422 case 0:
1423 string(file, " 1Q");
1424 break;
1425 case 1:
1426 string(file, " 2Q");
1427 break;
1428 case 2:
1429 string(file, " 3Q");
1430 break;
1431 case 3:
1432 string(file, " 4Q");
1433 break;
1434 }
1435 } else if (exec_size == 16) {
1436 if (qtr_ctl < 2)
1437 string(file, " 1H");
1438 else
1439 string(file, " 2H");
1440 }
1441 return 0;
1442 }
1443
1444 #ifdef DEBUG
1445 static __attribute__((__unused__)) int
1446 brw_disassemble_imm(const struct gen_device_info *devinfo,
1447 uint32_t dw3, uint32_t dw2, uint32_t dw1, uint32_t dw0)
1448 {
1449 brw_inst inst;
1450 inst.data[0] = (((uint64_t) dw1) << 32) | ((uint64_t) dw0);
1451 inst.data[1] = (((uint64_t) dw3) << 32) | ((uint64_t) dw2);
1452 return brw_disassemble_inst(stderr, devinfo, &inst, false);
1453 }
1454 #endif
1455
1456 int
1457 brw_disassemble_inst(FILE *file, const struct gen_device_info *devinfo,
1458 const brw_inst *inst, bool is_compacted)
1459 {
1460 int err = 0;
1461 int space = 0;
1462
1463 const enum opcode opcode = brw_inst_opcode(devinfo, inst);
1464 const struct opcode_desc *desc = brw_opcode_desc(devinfo, opcode);
1465
1466 if (brw_inst_pred_control(devinfo, inst)) {
1467 string(file, "(");
1468 err |= control(file, "predicate inverse", pred_inv,
1469 brw_inst_pred_inv(devinfo, inst), NULL);
1470 format(file, "f%"PRIu64, devinfo->gen >= 7 ? brw_inst_flag_reg_nr(devinfo, inst) : 0);
1471 if (brw_inst_flag_subreg_nr(devinfo, inst))
1472 format(file, ".%"PRIu64, brw_inst_flag_subreg_nr(devinfo, inst));
1473 if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1) {
1474 err |= control(file, "predicate control align1", pred_ctrl_align1,
1475 brw_inst_pred_control(devinfo, inst), NULL);
1476 } else {
1477 err |= control(file, "predicate control align16", pred_ctrl_align16,
1478 brw_inst_pred_control(devinfo, inst), NULL);
1479 }
1480 string(file, ") ");
1481 }
1482
1483 err |= print_opcode(file, devinfo, opcode);
1484 err |= control(file, "saturate", saturate, brw_inst_saturate(devinfo, inst),
1485 NULL);
1486
1487 err |= control(file, "debug control", debug_ctrl,
1488 brw_inst_debug_control(devinfo, inst), NULL);
1489
1490 if (opcode == BRW_OPCODE_MATH) {
1491 string(file, " ");
1492 err |= control(file, "function", math_function,
1493 brw_inst_math_function(devinfo, inst), NULL);
1494 } else if (opcode != BRW_OPCODE_SEND && opcode != BRW_OPCODE_SENDC) {
1495 err |= control(file, "conditional modifier", conditional_modifier,
1496 brw_inst_cond_modifier(devinfo, inst), NULL);
1497
1498 /* If we're using the conditional modifier, print which flags reg is
1499 * used for it. Note that on gen6+, the embedded-condition SEL and
1500 * control flow doesn't update flags.
1501 */
1502 if (brw_inst_cond_modifier(devinfo, inst) &&
1503 (devinfo->gen < 6 || (opcode != BRW_OPCODE_SEL &&
1504 opcode != BRW_OPCODE_IF &&
1505 opcode != BRW_OPCODE_WHILE))) {
1506 format(file, ".f%"PRIu64,
1507 devinfo->gen >= 7 ? brw_inst_flag_reg_nr(devinfo, inst) : 0);
1508 if (brw_inst_flag_subreg_nr(devinfo, inst))
1509 format(file, ".%"PRIu64, brw_inst_flag_subreg_nr(devinfo, inst));
1510 }
1511 }
1512
1513 if (opcode != BRW_OPCODE_NOP && opcode != BRW_OPCODE_NENOP) {
1514 string(file, "(");
1515 err |= control(file, "execution size", exec_size,
1516 brw_inst_exec_size(devinfo, inst), NULL);
1517 string(file, ")");
1518 }
1519
1520 if (opcode == BRW_OPCODE_SEND && devinfo->gen < 6)
1521 format(file, " %"PRIu64, brw_inst_base_mrf(devinfo, inst));
1522
1523 if (has_uip(devinfo, opcode)) {
1524 /* Instructions that have UIP also have JIP. */
1525 pad(file, 16);
1526 format(file, "JIP: %d", brw_inst_jip(devinfo, inst));
1527 pad(file, 32);
1528 format(file, "UIP: %d", brw_inst_uip(devinfo, inst));
1529 } else if (has_jip(devinfo, opcode)) {
1530 pad(file, 16);
1531 if (devinfo->gen >= 7) {
1532 format(file, "JIP: %d", brw_inst_jip(devinfo, inst));
1533 } else {
1534 format(file, "JIP: %d", brw_inst_gen6_jump_count(devinfo, inst));
1535 }
1536 } else if (devinfo->gen < 6 && (opcode == BRW_OPCODE_BREAK ||
1537 opcode == BRW_OPCODE_CONTINUE ||
1538 opcode == BRW_OPCODE_ELSE)) {
1539 pad(file, 16);
1540 format(file, "Jump: %d", brw_inst_gen4_jump_count(devinfo, inst));
1541 pad(file, 32);
1542 format(file, "Pop: %"PRIu64, brw_inst_gen4_pop_count(devinfo, inst));
1543 } else if (devinfo->gen < 6 && (opcode == BRW_OPCODE_IF ||
1544 opcode == BRW_OPCODE_IFF ||
1545 opcode == BRW_OPCODE_HALT)) {
1546 pad(file, 16);
1547 format(file, "Jump: %d", brw_inst_gen4_jump_count(devinfo, inst));
1548 } else if (devinfo->gen < 6 && opcode == BRW_OPCODE_ENDIF) {
1549 pad(file, 16);
1550 format(file, "Pop: %"PRIu64, brw_inst_gen4_pop_count(devinfo, inst));
1551 } else if (opcode == BRW_OPCODE_JMPI) {
1552 pad(file, 16);
1553 err |= src1(file, devinfo, inst);
1554 } else if (desc && desc->nsrc == 3) {
1555 pad(file, 16);
1556 err |= dest_3src(file, devinfo, inst);
1557
1558 pad(file, 32);
1559 err |= src0_3src(file, devinfo, inst);
1560
1561 pad(file, 48);
1562 err |= src1_3src(file, devinfo, inst);
1563
1564 pad(file, 64);
1565 err |= src2_3src(file, devinfo, inst);
1566 } else if (desc) {
1567 if (desc->ndst > 0) {
1568 pad(file, 16);
1569 err |= dest(file, devinfo, inst);
1570 }
1571
1572 if (desc->nsrc > 0) {
1573 pad(file, 32);
1574 err |= src0(file, devinfo, inst);
1575 }
1576
1577 if (desc->nsrc > 1) {
1578 pad(file, 48);
1579 err |= src1(file, devinfo, inst);
1580 }
1581 }
1582
1583 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC) {
1584 enum brw_message_target sfid = brw_inst_sfid(devinfo, inst);
1585
1586 if (brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
1587 /* show the indirect descriptor source */
1588 pad(file, 48);
1589 err |= src1(file, devinfo, inst);
1590 }
1591
1592 newline(file);
1593 pad(file, 16);
1594 space = 0;
1595
1596 fprintf(file, " ");
1597 err |= control(file, "SFID", devinfo->gen >= 6 ? gen6_sfid : gen4_sfid,
1598 sfid, &space);
1599
1600
1601 if (brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
1602 format(file, " indirect");
1603 } else {
1604 switch (sfid) {
1605 case BRW_SFID_MATH:
1606 err |= control(file, "math function", math_function,
1607 brw_inst_math_msg_function(devinfo, inst), &space);
1608 err |= control(file, "math saturate", math_saturate,
1609 brw_inst_math_msg_saturate(devinfo, inst), &space);
1610 err |= control(file, "math signed", math_signed,
1611 brw_inst_math_msg_signed_int(devinfo, inst), &space);
1612 err |= control(file, "math scalar", math_scalar,
1613 brw_inst_math_msg_data_type(devinfo, inst), &space);
1614 err |= control(file, "math precision", math_precision,
1615 brw_inst_math_msg_precision(devinfo, inst), &space);
1616 break;
1617 case BRW_SFID_SAMPLER:
1618 if (devinfo->gen >= 5) {
1619 err |= control(file, "sampler message", gen5_sampler_msg_type,
1620 brw_inst_sampler_msg_type(devinfo, inst), &space);
1621 err |= control(file, "sampler simd mode", gen5_sampler_simd_mode,
1622 brw_inst_sampler_simd_mode(devinfo, inst), &space);
1623 format(file, " Surface = %"PRIu64" Sampler = %"PRIu64,
1624 brw_inst_binding_table_index(devinfo, inst),
1625 brw_inst_sampler(devinfo, inst));
1626 } else {
1627 format(file, " (%"PRIu64", %"PRIu64", %"PRIu64", ",
1628 brw_inst_binding_table_index(devinfo, inst),
1629 brw_inst_sampler(devinfo, inst),
1630 brw_inst_sampler_msg_type(devinfo, inst));
1631 if (!devinfo->is_g4x) {
1632 err |= control(file, "sampler target format",
1633 sampler_target_format,
1634 brw_inst_sampler_return_format(devinfo, inst), NULL);
1635 }
1636 string(file, ")");
1637 }
1638 break;
1639 case GEN6_SFID_DATAPORT_SAMPLER_CACHE:
1640 case GEN6_SFID_DATAPORT_CONSTANT_CACHE:
1641 /* aka BRW_SFID_DATAPORT_READ on Gen4-5 */
1642 if (devinfo->gen >= 6) {
1643 format(file, " (%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64")",
1644 brw_inst_binding_table_index(devinfo, inst),
1645 brw_inst_dp_msg_control(devinfo, inst),
1646 brw_inst_dp_msg_type(devinfo, inst),
1647 devinfo->gen >= 7 ? 0 : brw_inst_dp_write_commit(devinfo, inst));
1648 } else {
1649 bool is_965 = devinfo->gen == 4 && !devinfo->is_g4x;
1650 err |= control(file, "DP read message type",
1651 is_965 ? gen4_dp_read_port_msg_type :
1652 g45_dp_read_port_msg_type,
1653 brw_inst_dp_read_msg_type(devinfo, inst),
1654 &space);
1655
1656 format(file, " MsgCtrl = 0x%"PRIx64,
1657 brw_inst_dp_read_msg_control(devinfo, inst));
1658
1659 format(file, " Surface = %"PRIu64, brw_inst_binding_table_index(devinfo, inst));
1660 }
1661 break;
1662
1663 case GEN6_SFID_DATAPORT_RENDER_CACHE: {
1664 /* aka BRW_SFID_DATAPORT_WRITE on Gen4-5 */
1665 unsigned msg_type = brw_inst_dp_write_msg_type(devinfo, inst);
1666
1667 err |= control(file, "DP rc message type",
1668 dp_rc_msg_type(devinfo), msg_type, &space);
1669
1670 bool is_rt_write = msg_type ==
1671 (devinfo->gen >= 6 ? GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE
1672 : BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE);
1673
1674 if (is_rt_write) {
1675 err |= control(file, "RT message type", m_rt_write_subtype,
1676 brw_inst_rt_message_type(devinfo, inst), &space);
1677 if (devinfo->gen >= 6 && brw_inst_rt_slot_group(devinfo, inst))
1678 string(file, " Hi");
1679 if (brw_inst_rt_last(devinfo, inst))
1680 string(file, " LastRT");
1681 if (devinfo->gen < 7 && brw_inst_dp_write_commit(devinfo, inst))
1682 string(file, " WriteCommit");
1683 } else {
1684 format(file, " MsgCtrl = 0x%"PRIx64,
1685 brw_inst_dp_write_msg_control(devinfo, inst));
1686 }
1687
1688 format(file, " Surface = %"PRIu64, brw_inst_binding_table_index(devinfo, inst));
1689 break;
1690 }
1691
1692 case BRW_SFID_URB: {
1693 unsigned opcode = brw_inst_urb_opcode(devinfo, inst);
1694
1695 format(file, " %"PRIu64, brw_inst_urb_global_offset(devinfo, inst));
1696
1697 space = 1;
1698
1699 err |= control(file, "urb opcode",
1700 devinfo->gen >= 7 ? gen7_urb_opcode
1701 : gen5_urb_opcode,
1702 opcode, &space);
1703
1704 if (devinfo->gen >= 7 &&
1705 brw_inst_urb_per_slot_offset(devinfo, inst)) {
1706 string(file, " per-slot");
1707 }
1708
1709 if (opcode == GEN8_URB_OPCODE_SIMD8_WRITE ||
1710 opcode == GEN8_URB_OPCODE_SIMD8_READ) {
1711 if (brw_inst_urb_channel_mask_present(devinfo, inst))
1712 string(file, " masked");
1713 } else {
1714 err |= control(file, "urb swizzle", urb_swizzle,
1715 brw_inst_urb_swizzle_control(devinfo, inst),
1716 &space);
1717 }
1718
1719 if (devinfo->gen < 7) {
1720 err |= control(file, "urb allocate", urb_allocate,
1721 brw_inst_urb_allocate(devinfo, inst), &space);
1722 err |= control(file, "urb used", urb_used,
1723 brw_inst_urb_used(devinfo, inst), &space);
1724 }
1725 if (devinfo->gen < 8) {
1726 err |= control(file, "urb complete", urb_complete,
1727 brw_inst_urb_complete(devinfo, inst), &space);
1728 }
1729 break;
1730 }
1731 case BRW_SFID_THREAD_SPAWNER:
1732 break;
1733
1734 case BRW_SFID_MESSAGE_GATEWAY:
1735 format(file, " (%s)",
1736 gen7_gateway_subfuncid[brw_inst_gateway_subfuncid(devinfo, inst)]);
1737 break;
1738
1739 case GEN7_SFID_DATAPORT_DATA_CACHE:
1740 if (devinfo->gen >= 7) {
1741 format(file, " (");
1742
1743 err |= control(file, "DP DC0 message type",
1744 dp_dc0_msg_type_gen7,
1745 brw_inst_dp_msg_type(devinfo, inst), &space);
1746
1747 format(file, ", %"PRIu64", ", brw_inst_binding_table_index(devinfo, inst));
1748
1749 switch (brw_inst_dp_msg_type(devinfo, inst)) {
1750 case GEN7_DATAPORT_DC_UNTYPED_ATOMIC_OP:
1751 control(file, "atomic op", aop,
1752 brw_inst_imm_ud(devinfo, inst) >> 8 & 0xf, &space);
1753 break;
1754 default:
1755 format(file, "%"PRIu64, brw_inst_dp_msg_control(devinfo, inst));
1756 }
1757 format(file, ")");
1758 break;
1759 }
1760 /* FALLTHROUGH */
1761
1762 case HSW_SFID_DATAPORT_DATA_CACHE_1: {
1763 if (devinfo->gen >= 7) {
1764 format(file, " (");
1765
1766 unsigned msg_ctrl = brw_inst_dp_msg_control(devinfo, inst);
1767
1768 err |= control(file, "DP DC1 message type",
1769 dp_dc1_msg_type_hsw,
1770 brw_inst_dp_msg_type(devinfo, inst), &space);
1771
1772 format(file, ", Surface = %"PRIu64", ",
1773 brw_inst_binding_table_index(devinfo, inst));
1774
1775 switch (brw_inst_dp_msg_type(devinfo, inst)) {
1776 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP:
1777 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP:
1778 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP:
1779 format(file, "SIMD%d,", (msg_ctrl & (1 << 4)) ? 8 : 16);
1780 /* fallthrough */
1781 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2:
1782 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2:
1783 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2:
1784 control(file, "atomic op", aop, msg_ctrl & 0xf, &space);
1785 break;
1786 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ:
1787 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE:
1788 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ:
1789 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE: {
1790 static const char *simd_modes[] = { "4x2", "16", "8" };
1791 format(file, "SIMD%s, Mask = 0x%x",
1792 simd_modes[msg_ctrl >> 4], msg_ctrl & 0xf);
1793 break;
1794 }
1795 default:
1796 format(file, "0x%x", msg_ctrl);
1797 }
1798 format(file, ")");
1799 break;
1800 }
1801 /* FALLTHROUGH */
1802 }
1803
1804 case GEN7_SFID_PIXEL_INTERPOLATOR:
1805 if (devinfo->gen >= 7) {
1806 format(file, " (%s, %s, 0x%02"PRIx64")",
1807 brw_inst_pi_nopersp(devinfo, inst) ? "linear" : "persp",
1808 pixel_interpolator_msg_types[brw_inst_pi_message_type(devinfo, inst)],
1809 brw_inst_pi_message_data(devinfo, inst));
1810 break;
1811 }
1812 /* FALLTHROUGH */
1813
1814 default:
1815 format(file, "unsupported shared function ID %d", sfid);
1816 break;
1817 }
1818
1819 if (space)
1820 string(file, " ");
1821 format(file, "mlen %"PRIu64, brw_inst_mlen(devinfo, inst));
1822 format(file, " rlen %"PRIu64, brw_inst_rlen(devinfo, inst));
1823 }
1824 }
1825 pad(file, 64);
1826 if (opcode != BRW_OPCODE_NOP && opcode != BRW_OPCODE_NENOP) {
1827 string(file, "{");
1828 space = 1;
1829 err |= control(file, "access mode", access_mode,
1830 brw_inst_access_mode(devinfo, inst), &space);
1831 if (devinfo->gen >= 6) {
1832 err |= control(file, "write enable control", wectrl,
1833 brw_inst_mask_control(devinfo, inst), &space);
1834 } else {
1835 err |= control(file, "mask control", mask_ctrl,
1836 brw_inst_mask_control(devinfo, inst), &space);
1837 }
1838 err |= control(file, "dependency control", dep_ctrl,
1839 ((brw_inst_no_dd_check(devinfo, inst) << 1) |
1840 brw_inst_no_dd_clear(devinfo, inst)), &space);
1841
1842 if (devinfo->gen >= 6)
1843 err |= qtr_ctrl(file, devinfo, inst);
1844 else {
1845 if (brw_inst_qtr_control(devinfo, inst) == BRW_COMPRESSION_COMPRESSED &&
1846 desc && desc->ndst > 0 &&
1847 brw_inst_dst_reg_file(devinfo, inst) == BRW_MESSAGE_REGISTER_FILE &&
1848 brw_inst_dst_da_reg_nr(devinfo, inst) & BRW_MRF_COMPR4) {
1849 format(file, " compr4");
1850 } else {
1851 err |= control(file, "compression control", compr_ctrl,
1852 brw_inst_qtr_control(devinfo, inst), &space);
1853 }
1854 }
1855
1856 err |= control(file, "compaction", cmpt_ctrl, is_compacted, &space);
1857 err |= control(file, "thread control", thread_ctrl,
1858 brw_inst_thread_control(devinfo, inst), &space);
1859 if (has_branch_ctrl(devinfo, opcode)) {
1860 err |= control(file, "branch ctrl", branch_ctrl,
1861 brw_inst_branch_control(devinfo, inst), &space);
1862 } else if (devinfo->gen >= 6) {
1863 err |= control(file, "acc write control", accwr,
1864 brw_inst_acc_wr_control(devinfo, inst), &space);
1865 }
1866 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC)
1867 err |= control(file, "end of thread", end_of_thread,
1868 brw_inst_eot(devinfo, inst), &space);
1869 if (space)
1870 string(file, " ");
1871 string(file, "}");
1872 }
1873 string(file, ";");
1874 newline(file);
1875 return err;
1876 }