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