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 <stdlib.h>
25#include <string.h>
26#include <getopt.h>
27#include <unistd.h>
28#include <stdarg.h>
29
30#include "main/mtypes.h"
31
32#include "brw_context.h"
33#include "brw_defines.h"
34
35struct {
36    char    *name;
37    int	    nsrc;
38    int	    ndst;
39} opcode[128] = {
40    [BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 },
41    [BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 },
42    [BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 },
43    [BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 },
44    [BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 },
45    [BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 },
46    [BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 },
47    [BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 },
48
49    [BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 },
50    [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 },
51    [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 },
52    [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 },
53    [BRW_OPCODE_PLN] = { .name = "pln", .nsrc = 2, .ndst = 1 },
54    [BRW_OPCODE_MAD] = { .name = "mad", .nsrc = 3, .ndst = 1 },
55    [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 },
56    [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 },
57    [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 },
58    [BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 },
59    [BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 },
60    [BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 },
61    [BRW_OPCODE_MATH] = { .name = "math", .nsrc = 2, .ndst = 1 },
62
63    [BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 },
64    [BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 },
65    [BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 },
66    [BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 },
67    [BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 },
68    [BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 },
69    [BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 },
70    [BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 },
71    [BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 },
72    [BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 },
73    [BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 },
74
75    [BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 },
76    [BRW_OPCODE_SENDC] = { .name = "sendc", .nsrc = 1, .ndst = 1 },
77    [BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 },
78    [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 0, .ndst = 0 },
79    [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 },
80    [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 2, .ndst = 1 },
81    [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 },
82    [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 },
83    [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 },
84    [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 },
85    [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 },
86    [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 },
87    [BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 },
88    [BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 },
89    [BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 },
90    [BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 },
91    [BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 },
92    [BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 },
93};
94
95char *conditional_modifier[16] = {
96    [BRW_CONDITIONAL_NONE] = "",
97    [BRW_CONDITIONAL_Z] = ".e",
98    [BRW_CONDITIONAL_NZ] = ".ne",
99    [BRW_CONDITIONAL_G] = ".g",
100    [BRW_CONDITIONAL_GE] = ".ge",
101    [BRW_CONDITIONAL_L] = ".l",
102    [BRW_CONDITIONAL_LE] = ".le",
103    [BRW_CONDITIONAL_R] = ".r",
104    [BRW_CONDITIONAL_O] = ".o",
105    [BRW_CONDITIONAL_U] = ".u",
106};
107
108char *negate[2] = {
109    [0] = "",
110    [1] = "-",
111};
112
113char *_abs[2] = {
114    [0] = "",
115    [1] = "(abs)",
116};
117
118char *vert_stride[16] = {
119    [0] = "0",
120    [1] = "1",
121    [2] = "2",
122    [3] = "4",
123    [4] = "8",
124    [5] = "16",
125    [6] = "32",
126    [15] = "VxH",
127};
128
129char *width[8] = {
130    [0] = "1",
131    [1] = "2",
132    [2] = "4",
133    [3] = "8",
134    [4] = "16",
135};
136
137char *horiz_stride[4] = {
138    [0] = "0",
139    [1] = "1",
140    [2] = "2",
141    [3] = "4"
142};
143
144char *chan_sel[4] = {
145    [0] = "x",
146    [1] = "y",
147    [2] = "z",
148    [3] = "w",
149};
150
151char *dest_condmod[16] = {
152};
153
154char *debug_ctrl[2] = {
155    [0] = "",
156    [1] = ".breakpoint"
157};
158
159char *saturate[2] = {
160    [0] = "",
161    [1] = ".sat"
162};
163
164char *accwr[2] = {
165    [0] = "",
166    [1] = "AccWrEnable"
167};
168
169char *wectrl[2] = {
170    [0] = "WE_normal",
171    [1] = "WE_all"
172};
173
174char *exec_size[8] = {
175    [0] = "1",
176    [1] = "2",
177    [2] = "4",
178    [3] = "8",
179    [4] = "16",
180    [5] = "32"
181};
182
183char *pred_inv[2] = {
184    [0] = "+",
185    [1] = "-"
186};
187
188char *pred_ctrl_align16[16] = {
189    [1] = "",
190    [2] = ".x",
191    [3] = ".y",
192    [4] = ".z",
193    [5] = ".w",
194    [6] = ".any4h",
195    [7] = ".all4h",
196};
197
198char *pred_ctrl_align1[16] = {
199    [1] = "",
200    [2] = ".anyv",
201    [3] = ".allv",
202    [4] = ".any2h",
203    [5] = ".all2h",
204    [6] = ".any4h",
205    [7] = ".all4h",
206    [8] = ".any8h",
207    [9] = ".all8h",
208    [10] = ".any16h",
209    [11] = ".all16h",
210};
211
212char *thread_ctrl[4] = {
213    [0] = "",
214    [2] = "switch"
215};
216
217char *compr_ctrl[4] = {
218    [0] = "",
219    [1] = "sechalf",
220    [2] = "compr",
221    [3] = "compr4",
222};
223
224char *dep_ctrl[4] = {
225    [0] = "",
226    [1] = "NoDDClr",
227    [2] = "NoDDChk",
228    [3] = "NoDDClr,NoDDChk",
229};
230
231char *mask_ctrl[4] = {
232    [0] = "",
233    [1] = "nomask",
234};
235
236char *access_mode[2] = {
237    [0] = "align1",
238    [1] = "align16",
239};
240
241char *reg_encoding[8] = {
242    [0] = "UD",
243    [1] = "D",
244    [2] = "UW",
245    [3] = "W",
246    [4] = "UB",
247    [5] = "B",
248    [7] = "F"
249};
250
251int reg_type_size[8] = {
252    [0] = 4,
253    [1] = 4,
254    [2] = 2,
255    [3] = 2,
256    [4] = 1,
257    [5] = 1,
258    [7] = 4
259};
260
261char *imm_encoding[8] = {
262    [0] = "UD",
263    [1] = "D",
264    [2] = "UW",
265    [3] = "W",
266    [5] = "VF",
267    [6] = "V",
268    [7] = "F"
269};
270
271char *reg_file[4] = {
272    [0] = "A",
273    [1] = "g",
274    [2] = "m",
275    [3] = "imm",
276};
277
278char *writemask[16] = {
279    [0x0] = ".",
280    [0x1] = ".x",
281    [0x2] = ".y",
282    [0x3] = ".xy",
283    [0x4] = ".z",
284    [0x5] = ".xz",
285    [0x6] = ".yz",
286    [0x7] = ".xyz",
287    [0x8] = ".w",
288    [0x9] = ".xw",
289    [0xa] = ".yw",
290    [0xb] = ".xyw",
291    [0xc] = ".zw",
292    [0xd] = ".xzw",
293    [0xe] = ".yzw",
294    [0xf] = "",
295};
296
297char *end_of_thread[2] = {
298    [0] = "",
299    [1] = "EOT"
300};
301
302char *target_function[16] = {
303    [BRW_SFID_NULL] = "null",
304    [BRW_SFID_MATH] = "math",
305    [BRW_SFID_SAMPLER] = "sampler",
306    [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
307    [BRW_SFID_DATAPORT_READ] = "read",
308    [BRW_SFID_DATAPORT_WRITE] = "write",
309    [BRW_SFID_URB] = "urb",
310    [BRW_SFID_THREAD_SPAWNER] = "thread_spawner"
311};
312
313char *target_function_gen6[16] = {
314    [BRW_SFID_NULL] = "null",
315    [BRW_SFID_MATH] = "math",
316    [BRW_SFID_SAMPLER] = "sampler",
317    [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
318    [BRW_SFID_URB] = "urb",
319    [BRW_SFID_THREAD_SPAWNER] = "thread_spawner",
320    [GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "sampler",
321    [GEN6_SFID_DATAPORT_RENDER_CACHE] = "render",
322    [GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "const",
323    [GEN7_SFID_DATAPORT_DATA_CACHE] = "data"
324};
325
326char *dp_rc_msg_type_gen6[16] = {
327    [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
328    [GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
329    [GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
330    [GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read",
331    [GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] = "OWORD unaligned block read",
332    [GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read",
333    [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write",
334    [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write",
335    [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] = "OWORD dual block write",
336    [GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write",
337    [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] = "DWORD scattered write",
338    [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write",
339    [GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write",
340    [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORMc write",
341};
342
343char *math_function[16] = {
344    [BRW_MATH_FUNCTION_INV] = "inv",
345    [BRW_MATH_FUNCTION_LOG] = "log",
346    [BRW_MATH_FUNCTION_EXP] = "exp",
347    [BRW_MATH_FUNCTION_SQRT] = "sqrt",
348    [BRW_MATH_FUNCTION_RSQ] = "rsq",
349    [BRW_MATH_FUNCTION_SIN] = "sin",
350    [BRW_MATH_FUNCTION_COS] = "cos",
351    [BRW_MATH_FUNCTION_SINCOS] = "sincos",
352    [BRW_MATH_FUNCTION_TAN] = "tan",
353    [BRW_MATH_FUNCTION_POW] = "pow",
354    [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
355    [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
356    [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
357};
358
359char *math_saturate[2] = {
360    [0] = "",
361    [1] = "sat"
362};
363
364char *math_signed[2] = {
365    [0] = "",
366    [1] = "signed"
367};
368
369char *math_scalar[2] = {
370    [0] = "",
371    [1] = "scalar"
372};
373
374char *math_precision[2] = {
375    [0] = "",
376    [1] = "partial_precision"
377};
378
379char *urb_opcode[2] = {
380    [0] = "urb_write",
381    [1] = "ff_sync",
382};
383
384char *urb_swizzle[4] = {
385    [BRW_URB_SWIZZLE_NONE] = "",
386    [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
387    [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose",
388};
389
390char *urb_allocate[2] = {
391    [0] = "",
392    [1] = "allocate"
393};
394
395char *urb_used[2] = {
396    [0] = "",
397    [1] = "used"
398};
399
400char *urb_complete[2] = {
401    [0] = "",
402    [1] = "complete"
403};
404
405char *sampler_target_format[4] = {
406    [0] = "F",
407    [2] = "UD",
408    [3] = "D"
409};
410
411
412static int column;
413
414static int string (FILE *file, char *string)
415{
416    fputs (string, file);
417    column += strlen (string);
418    return 0;
419}
420
421static int format (FILE *f, char *format, ...)
422{
423    char    buf[1024];
424    va_list	args;
425    va_start (args, format);
426
427    vsnprintf (buf, sizeof (buf) - 1, format, args);
428    va_end (args);
429    string (f, buf);
430    return 0;
431}
432
433static int newline (FILE *f)
434{
435    putc ('\n', f);
436    column = 0;
437    return 0;
438}
439
440static int pad (FILE *f, int c)
441{
442    do
443	string (f, " ");
444    while (column < c);
445    return 0;
446}
447
448static int control (FILE *file, char *name, char *ctrl[], GLuint id, int *space)
449{
450    if (!ctrl[id]) {
451	fprintf (file, "*** invalid %s value %d ",
452		 name, id);
453	return 1;
454    }
455    if (ctrl[id][0])
456    {
457	if (space && *space)
458	    string (file, " ");
459	string (file, ctrl[id]);
460	if (space)
461	    *space = 1;
462    }
463    return 0;
464}
465
466static int print_opcode (FILE *file, int id)
467{
468    if (!opcode[id].name) {
469	format (file, "*** invalid opcode value %d ", id);
470	return 1;
471    }
472    string (file, opcode[id].name);
473    return 0;
474}
475
476static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr)
477{
478    int	err = 0;
479
480    /* Clear the Compr4 instruction compression bit. */
481    if (_reg_file == BRW_MESSAGE_REGISTER_FILE)
482       _reg_nr &= ~(1 << 7);
483
484    if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
485	switch (_reg_nr & 0xf0) {
486	case BRW_ARF_NULL:
487	    string (file, "null");
488	    return -1;
489	case BRW_ARF_ADDRESS:
490	    format (file, "a%d", _reg_nr & 0x0f);
491	    break;
492	case BRW_ARF_ACCUMULATOR:
493	    format (file, "acc%d", _reg_nr & 0x0f);
494	    break;
495	case BRW_ARF_FLAG:
496	    format (file, "f%d", _reg_nr & 0x0f);
497	    break;
498	case BRW_ARF_MASK:
499	    format (file, "mask%d", _reg_nr & 0x0f);
500	    break;
501	case BRW_ARF_MASK_STACK:
502	    format (file, "msd%d", _reg_nr & 0x0f);
503	    break;
504	case BRW_ARF_STATE:
505	    format (file, "sr%d", _reg_nr & 0x0f);
506	    break;
507	case BRW_ARF_CONTROL:
508	    format (file, "cr%d", _reg_nr & 0x0f);
509	    break;
510	case BRW_ARF_NOTIFICATION_COUNT:
511	    format (file, "n%d", _reg_nr & 0x0f);
512	    break;
513	case BRW_ARF_IP:
514	    string (file, "ip");
515	    return -1;
516	    break;
517	default:
518	    format (file, "ARF%d", _reg_nr);
519	    break;
520	}
521    } else {
522	err  |= control (file, "src reg file", reg_file, _reg_file, NULL);
523	format (file, "%d", _reg_nr);
524    }
525    return err;
526}
527
528static int dest (FILE *file, struct brw_instruction *inst)
529{
530    int	err = 0;
531
532    if (inst->header.access_mode == BRW_ALIGN_1)
533    {
534	if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT)
535	{
536	    err |= reg (file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr);
537	    if (err == -1)
538		return 0;
539	    if (inst->bits1.da1.dest_subreg_nr)
540		format (file, ".%d", inst->bits1.da1.dest_subreg_nr /
541				     reg_type_size[inst->bits1.da1.dest_reg_type]);
542	    string (file, "<");
543	    err |= control (file, "horiz stride", horiz_stride, inst->bits1.da1.dest_horiz_stride, NULL);
544	    string (file, ">");
545	    err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL);
546	}
547	else
548	{
549	    string (file, "g[a0");
550	    if (inst->bits1.ia1.dest_subreg_nr)
551		format (file, ".%d", inst->bits1.ia1.dest_subreg_nr /
552					reg_type_size[inst->bits1.ia1.dest_reg_type]);
553	    if (inst->bits1.ia1.dest_indirect_offset)
554		format (file, " %d", inst->bits1.ia1.dest_indirect_offset);
555	    string (file, "]<");
556	    err |= control (file, "horiz stride", horiz_stride, inst->bits1.ia1.dest_horiz_stride, NULL);
557	    string (file, ">");
558	    err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL);
559	}
560    }
561    else
562    {
563	if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT)
564	{
565	    err |= reg (file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr);
566	    if (err == -1)
567		return 0;
568	    if (inst->bits1.da16.dest_subreg_nr)
569		format (file, ".%d", inst->bits1.da16.dest_subreg_nr /
570				     reg_type_size[inst->bits1.da16.dest_reg_type]);
571	    string (file, "<1>");
572	    err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL);
573	    err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL);
574	}
575	else
576	{
577	    err = 1;
578	    string (file, "Indirect align16 address mode not supported");
579	}
580    }
581
582    return 0;
583}
584
585static int dest_3src (FILE *file, struct brw_instruction *inst)
586{
587    int	err = 0;
588    uint32_t reg_file;
589
590    if (inst->bits1.da3src.dest_reg_file)
591       reg_file = BRW_MESSAGE_REGISTER_FILE;
592    else
593       reg_file = BRW_GENERAL_REGISTER_FILE;
594
595    err |= reg (file, reg_file, inst->bits1.da3src.dest_reg_nr);
596    if (err == -1)
597       return 0;
598    if (inst->bits1.da3src.dest_subreg_nr)
599       format (file, ".%d", inst->bits1.da3src.dest_subreg_nr);
600    string (file, "<1>");
601    err |= control (file, "writemask", writemask, inst->bits1.da3src.dest_writemask, NULL);
602    err |= control (file, "dest reg encoding", reg_encoding, BRW_REGISTER_TYPE_F, NULL);
603
604    return 0;
605}
606
607static int src_align1_region (FILE *file,
608			      GLuint _vert_stride, GLuint _width, GLuint _horiz_stride)
609{
610    int err = 0;
611    string (file, "<");
612    err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
613    string (file, ",");
614    err |= control (file, "width", width, _width, NULL);
615    string (file, ",");
616    err |= control (file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
617    string (file, ">");
618    return err;
619}
620
621static int src_da1 (FILE *file, GLuint type, GLuint _reg_file,
622		    GLuint _vert_stride, GLuint _width, GLuint _horiz_stride,
623		    GLuint reg_num, GLuint sub_reg_num, GLuint __abs, GLuint _negate)
624{
625    int err = 0;
626    err |= control (file, "negate", negate, _negate, NULL);
627    err |= control (file, "abs", _abs, __abs, NULL);
628
629    err |= reg (file, _reg_file, reg_num);
630    if (err == -1)
631	return 0;
632    if (sub_reg_num)
633	format (file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
634    src_align1_region (file, _vert_stride, _width, _horiz_stride);
635    err |= control (file, "src reg encoding", reg_encoding, type, NULL);
636    return err;
637}
638
639static int src_ia1 (FILE *file,
640		    GLuint type,
641		    GLuint _reg_file,
642		    GLint _addr_imm,
643		    GLuint _addr_subreg_nr,
644		    GLuint _negate,
645		    GLuint __abs,
646		    GLuint _addr_mode,
647		    GLuint _horiz_stride,
648		    GLuint _width,
649		    GLuint _vert_stride)
650{
651    int err = 0;
652    err |= control (file, "negate", negate, _negate, NULL);
653    err |= control (file, "abs", _abs, __abs, NULL);
654
655    string (file, "g[a0");
656    if (_addr_subreg_nr)
657	format (file, ".%d", _addr_subreg_nr);
658    if (_addr_imm)
659	format (file, " %d", _addr_imm);
660    string (file, "]");
661    src_align1_region (file, _vert_stride, _width, _horiz_stride);
662    err |= control (file, "src reg encoding", reg_encoding, type, NULL);
663    return err;
664}
665
666static int src_da16 (FILE *file,
667		     GLuint _reg_type,
668		     GLuint _reg_file,
669		     GLuint _vert_stride,
670		     GLuint _reg_nr,
671		     GLuint _subreg_nr,
672		     GLuint __abs,
673		     GLuint _negate,
674		     GLuint swz_x,
675		     GLuint swz_y,
676		     GLuint swz_z,
677		     GLuint swz_w)
678{
679    int err = 0;
680    err |= control (file, "negate", negate, _negate, NULL);
681    err |= control (file, "abs", _abs, __abs, NULL);
682
683    err |= reg (file, _reg_file, _reg_nr);
684    if (err == -1)
685	return 0;
686    if (_subreg_nr)
687	/* bit4 for subreg number byte addressing. Make this same meaning as
688	   in da1 case, so output looks consistent. */
689	format (file, ".%d", 16 / reg_type_size[_reg_type]);
690    string (file, "<");
691    err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
692    string (file, ",4,1>");
693    /*
694     * Three kinds of swizzle display:
695     *  identity - nothing printed
696     *  1->all	 - print the single channel
697     *  1->1     - print the mapping
698     */
699    if (swz_x == BRW_CHANNEL_X &&
700	swz_y == BRW_CHANNEL_Y &&
701	swz_z == BRW_CHANNEL_Z &&
702	swz_w == BRW_CHANNEL_W)
703    {
704	;
705    }
706    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
707    {
708	string (file, ".");
709	err |= control (file, "channel select", chan_sel, swz_x, NULL);
710    }
711    else
712    {
713	string (file, ".");
714	err |= control (file, "channel select", chan_sel, swz_x, NULL);
715	err |= control (file, "channel select", chan_sel, swz_y, NULL);
716	err |= control (file, "channel select", chan_sel, swz_z, NULL);
717	err |= control (file, "channel select", chan_sel, swz_w, NULL);
718    }
719    err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL);
720    return err;
721}
722
723static int src0_3src (FILE *file, struct brw_instruction *inst)
724{
725    int err = 0;
726    GLuint swz_x = (inst->bits2.da3src.src0_swizzle >> 0) & 0x3;
727    GLuint swz_y = (inst->bits2.da3src.src0_swizzle >> 2) & 0x3;
728    GLuint swz_z = (inst->bits2.da3src.src0_swizzle >> 4) & 0x3;
729    GLuint swz_w = (inst->bits2.da3src.src0_swizzle >> 6) & 0x3;
730
731    err |= control (file, "negate", negate, inst->bits1.da3src.src0_negate, NULL);
732    err |= control (file, "abs", _abs, inst->bits1.da3src.src0_abs, NULL);
733
734    err |= reg (file, BRW_GENERAL_REGISTER_FILE, inst->bits2.da3src.src0_reg_nr);
735    if (err == -1)
736	return 0;
737    if (inst->bits2.da3src.src0_subreg_nr)
738	format (file, ".%d", inst->bits2.da3src.src0_subreg_nr);
739    string (file, "<4,1,1>");
740    err |= control (file, "src da16 reg type", reg_encoding,
741		    BRW_REGISTER_TYPE_F, NULL);
742    /*
743     * Three kinds of swizzle display:
744     *  identity - nothing printed
745     *  1->all	 - print the single channel
746     *  1->1     - print the mapping
747     */
748    if (swz_x == BRW_CHANNEL_X &&
749	swz_y == BRW_CHANNEL_Y &&
750	swz_z == BRW_CHANNEL_Z &&
751	swz_w == BRW_CHANNEL_W)
752    {
753	;
754    }
755    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
756    {
757	string (file, ".");
758	err |= control (file, "channel select", chan_sel, swz_x, NULL);
759    }
760    else
761    {
762	string (file, ".");
763	err |= control (file, "channel select", chan_sel, swz_x, NULL);
764	err |= control (file, "channel select", chan_sel, swz_y, NULL);
765	err |= control (file, "channel select", chan_sel, swz_z, NULL);
766	err |= control (file, "channel select", chan_sel, swz_w, NULL);
767    }
768    return err;
769}
770
771static int src1_3src (FILE *file, struct brw_instruction *inst)
772{
773    int err = 0;
774    GLuint swz_x = (inst->bits2.da3src.src1_swizzle >> 0) & 0x3;
775    GLuint swz_y = (inst->bits2.da3src.src1_swizzle >> 2) & 0x3;
776    GLuint swz_z = (inst->bits2.da3src.src1_swizzle >> 4) & 0x3;
777    GLuint swz_w = (inst->bits2.da3src.src1_swizzle >> 6) & 0x3;
778    GLuint src1_subreg_nr = (inst->bits2.da3src.src1_subreg_nr_low |
779			     (inst->bits3.da3src.src1_subreg_nr_high << 2));
780
781    err |= control (file, "negate", negate, inst->bits1.da3src.src1_negate,
782		    NULL);
783    err |= control (file, "abs", _abs, inst->bits1.da3src.src1_abs, NULL);
784
785    err |= reg (file, BRW_GENERAL_REGISTER_FILE,
786		inst->bits3.da3src.src1_reg_nr);
787    if (err == -1)
788	return 0;
789    if (src1_subreg_nr)
790	format (file, ".%d", src1_subreg_nr);
791    string (file, "<4,1,1>");
792    err |= control (file, "src da16 reg type", reg_encoding,
793		    BRW_REGISTER_TYPE_F, NULL);
794    /*
795     * Three kinds of swizzle display:
796     *  identity - nothing printed
797     *  1->all	 - print the single channel
798     *  1->1     - print the mapping
799     */
800    if (swz_x == BRW_CHANNEL_X &&
801	swz_y == BRW_CHANNEL_Y &&
802	swz_z == BRW_CHANNEL_Z &&
803	swz_w == BRW_CHANNEL_W)
804    {
805	;
806    }
807    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
808    {
809	string (file, ".");
810	err |= control (file, "channel select", chan_sel, swz_x, NULL);
811    }
812    else
813    {
814	string (file, ".");
815	err |= control (file, "channel select", chan_sel, swz_x, NULL);
816	err |= control (file, "channel select", chan_sel, swz_y, NULL);
817	err |= control (file, "channel select", chan_sel, swz_z, NULL);
818	err |= control (file, "channel select", chan_sel, swz_w, NULL);
819    }
820    return err;
821}
822
823
824static int src2_3src (FILE *file, struct brw_instruction *inst)
825{
826    int err = 0;
827    GLuint swz_x = (inst->bits3.da3src.src2_swizzle >> 0) & 0x3;
828    GLuint swz_y = (inst->bits3.da3src.src2_swizzle >> 2) & 0x3;
829    GLuint swz_z = (inst->bits3.da3src.src2_swizzle >> 4) & 0x3;
830    GLuint swz_w = (inst->bits3.da3src.src2_swizzle >> 6) & 0x3;
831
832    err |= control (file, "negate", negate, inst->bits1.da3src.src2_negate,
833		    NULL);
834    err |= control (file, "abs", _abs, inst->bits1.da3src.src2_abs, NULL);
835
836    err |= reg (file, BRW_GENERAL_REGISTER_FILE,
837		inst->bits3.da3src.src2_reg_nr);
838    if (err == -1)
839	return 0;
840    if (inst->bits3.da3src.src2_subreg_nr)
841	format (file, ".%d", inst->bits3.da3src.src2_subreg_nr);
842    string (file, "<4,1,1>");
843    err |= control (file, "src da16 reg type", reg_encoding,
844		    BRW_REGISTER_TYPE_F, NULL);
845    /*
846     * Three kinds of swizzle display:
847     *  identity - nothing printed
848     *  1->all	 - print the single channel
849     *  1->1     - print the mapping
850     */
851    if (swz_x == BRW_CHANNEL_X &&
852	swz_y == BRW_CHANNEL_Y &&
853	swz_z == BRW_CHANNEL_Z &&
854	swz_w == BRW_CHANNEL_W)
855    {
856	;
857    }
858    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
859    {
860	string (file, ".");
861	err |= control (file, "channel select", chan_sel, swz_x, NULL);
862    }
863    else
864    {
865	string (file, ".");
866	err |= control (file, "channel select", chan_sel, swz_x, NULL);
867	err |= control (file, "channel select", chan_sel, swz_y, NULL);
868	err |= control (file, "channel select", chan_sel, swz_z, NULL);
869	err |= control (file, "channel select", chan_sel, swz_w, NULL);
870    }
871    return err;
872}
873
874static int imm (FILE *file, GLuint type, struct brw_instruction *inst) {
875    switch (type) {
876    case BRW_REGISTER_TYPE_UD:
877	format (file, "0x%08xUD", inst->bits3.ud);
878	break;
879    case BRW_REGISTER_TYPE_D:
880	format (file, "%dD", inst->bits3.d);
881	break;
882    case BRW_REGISTER_TYPE_UW:
883	format (file, "0x%04xUW", (uint16_t) inst->bits3.ud);
884	break;
885    case BRW_REGISTER_TYPE_W:
886	format (file, "%dW", (int16_t) inst->bits3.d);
887	break;
888    case BRW_REGISTER_TYPE_UB:
889	format (file, "0x%02xUB", (int8_t) inst->bits3.ud);
890	break;
891    case BRW_REGISTER_TYPE_VF:
892	format (file, "Vector Float");
893	break;
894    case BRW_REGISTER_TYPE_V:
895	format (file, "0x%08xV", inst->bits3.ud);
896	break;
897    case BRW_REGISTER_TYPE_F:
898	format (file, "%-gF", inst->bits3.f);
899    }
900    return 0;
901}
902
903static int src0 (FILE *file, struct brw_instruction *inst)
904{
905    if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE)
906	return imm (file, inst->bits1.da1.src0_reg_type,
907		    inst);
908    else if (inst->header.access_mode == BRW_ALIGN_1)
909    {
910	if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT)
911	{
912	    return src_da1 (file,
913			    inst->bits1.da1.src0_reg_type,
914			    inst->bits1.da1.src0_reg_file,
915			    inst->bits2.da1.src0_vert_stride,
916			    inst->bits2.da1.src0_width,
917			    inst->bits2.da1.src0_horiz_stride,
918			    inst->bits2.da1.src0_reg_nr,
919			    inst->bits2.da1.src0_subreg_nr,
920			    inst->bits2.da1.src0_abs,
921			    inst->bits2.da1.src0_negate);
922	}
923	else
924	{
925	    return src_ia1 (file,
926			    inst->bits1.ia1.src0_reg_type,
927			    inst->bits1.ia1.src0_reg_file,
928			    inst->bits2.ia1.src0_indirect_offset,
929			    inst->bits2.ia1.src0_subreg_nr,
930			    inst->bits2.ia1.src0_negate,
931			    inst->bits2.ia1.src0_abs,
932			    inst->bits2.ia1.src0_address_mode,
933			    inst->bits2.ia1.src0_horiz_stride,
934			    inst->bits2.ia1.src0_width,
935			    inst->bits2.ia1.src0_vert_stride);
936	}
937    }
938    else
939    {
940	if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT)
941	{
942	    return src_da16 (file,
943			     inst->bits1.da16.src0_reg_type,
944			     inst->bits1.da16.src0_reg_file,
945			     inst->bits2.da16.src0_vert_stride,
946			     inst->bits2.da16.src0_reg_nr,
947			     inst->bits2.da16.src0_subreg_nr,
948			     inst->bits2.da16.src0_abs,
949			     inst->bits2.da16.src0_negate,
950			     inst->bits2.da16.src0_swz_x,
951			     inst->bits2.da16.src0_swz_y,
952			     inst->bits2.da16.src0_swz_z,
953			     inst->bits2.da16.src0_swz_w);
954	}
955	else
956	{
957	    string (file, "Indirect align16 address mode not supported");
958	    return 1;
959	}
960    }
961}
962
963static int src1 (FILE *file, struct brw_instruction *inst)
964{
965    if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE)
966	return imm (file, inst->bits1.da1.src1_reg_type,
967		    inst);
968    else if (inst->header.access_mode == BRW_ALIGN_1)
969    {
970	if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT)
971	{
972	    return src_da1 (file,
973			    inst->bits1.da1.src1_reg_type,
974			    inst->bits1.da1.src1_reg_file,
975			    inst->bits3.da1.src1_vert_stride,
976			    inst->bits3.da1.src1_width,
977			    inst->bits3.da1.src1_horiz_stride,
978			    inst->bits3.da1.src1_reg_nr,
979			    inst->bits3.da1.src1_subreg_nr,
980			    inst->bits3.da1.src1_abs,
981			    inst->bits3.da1.src1_negate);
982	}
983	else
984	{
985	    return src_ia1 (file,
986			    inst->bits1.ia1.src1_reg_type,
987			    inst->bits1.ia1.src1_reg_file,
988			    inst->bits3.ia1.src1_indirect_offset,
989			    inst->bits3.ia1.src1_subreg_nr,
990			    inst->bits3.ia1.src1_negate,
991			    inst->bits3.ia1.src1_abs,
992			    inst->bits3.ia1.src1_address_mode,
993			    inst->bits3.ia1.src1_horiz_stride,
994			    inst->bits3.ia1.src1_width,
995			    inst->bits3.ia1.src1_vert_stride);
996	}
997    }
998    else
999    {
1000	if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT)
1001	{
1002	    return src_da16 (file,
1003			     inst->bits1.da16.src1_reg_type,
1004			     inst->bits1.da16.src1_reg_file,
1005			     inst->bits3.da16.src1_vert_stride,
1006			     inst->bits3.da16.src1_reg_nr,
1007			     inst->bits3.da16.src1_subreg_nr,
1008			     inst->bits3.da16.src1_abs,
1009			     inst->bits3.da16.src1_negate,
1010			     inst->bits3.da16.src1_swz_x,
1011			     inst->bits3.da16.src1_swz_y,
1012			     inst->bits3.da16.src1_swz_z,
1013			     inst->bits3.da16.src1_swz_w);
1014	}
1015	else
1016	{
1017	    string (file, "Indirect align16 address mode not supported");
1018	    return 1;
1019	}
1020    }
1021}
1022
1023int esize[6] = {
1024	[0] = 1,
1025	[1] = 2,
1026	[2] = 4,
1027	[3] = 8,
1028	[4] = 16,
1029	[5] = 32,
1030};
1031
1032static int qtr_ctrl(FILE *file, struct brw_instruction *inst)
1033{
1034    int qtr_ctl = inst->header.compression_control;
1035    int exec_size = esize[inst->header.execution_size];
1036
1037    if (exec_size == 8) {
1038	switch (qtr_ctl) {
1039	case 0:
1040	    string (file, " 1Q");
1041	    break;
1042	case 1:
1043	    string (file, " 2Q");
1044	    break;
1045	case 2:
1046	    string (file, " 3Q");
1047	    break;
1048	case 3:
1049	    string (file, " 4Q");
1050	    break;
1051	}
1052    } else if (exec_size == 16){
1053	if (qtr_ctl < 2)
1054	    string (file, " 1H");
1055	else
1056	    string (file, " 2H");
1057    }
1058    return 0;
1059}
1060
1061int brw_disasm (FILE *file, struct brw_instruction *inst, int gen)
1062{
1063    int	err = 0;
1064    int space = 0;
1065
1066    if (inst->header.predicate_control) {
1067	string (file, "(");
1068	err |= control (file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL);
1069	string (file, "f0");
1070	if (inst->bits2.da1.flag_reg_nr)
1071	    format (file, ".%d", inst->bits2.da1.flag_reg_nr);
1072	if (inst->header.access_mode == BRW_ALIGN_1)
1073	    err |= control (file, "predicate control align1", pred_ctrl_align1,
1074			    inst->header.predicate_control, NULL);
1075	else
1076	    err |= control (file, "predicate control align16", pred_ctrl_align16,
1077			    inst->header.predicate_control, NULL);
1078	string (file, ") ");
1079    }
1080
1081    err |= print_opcode (file, inst->header.opcode);
1082    err |= control (file, "saturate", saturate, inst->header.saturate, NULL);
1083    err |= control (file, "debug control", debug_ctrl, inst->header.debug_control, NULL);
1084
1085    if (inst->header.opcode == BRW_OPCODE_MATH) {
1086	string (file, " ");
1087	err |= control (file, "function", math_function,
1088			inst->header.destreg__conditionalmod, NULL);
1089    } else if (inst->header.opcode != BRW_OPCODE_SEND &&
1090	       inst->header.opcode != BRW_OPCODE_SENDC)
1091	err |= control (file, "conditional modifier", conditional_modifier,
1092			inst->header.destreg__conditionalmod, NULL);
1093
1094    if (inst->header.opcode != BRW_OPCODE_NOP) {
1095	string (file, "(");
1096	err |= control (file, "execution size", exec_size, inst->header.execution_size, NULL);
1097	string (file, ")");
1098    }
1099
1100    if (inst->header.opcode == BRW_OPCODE_SEND && gen < 6)
1101	format (file, " %d", inst->header.destreg__conditionalmod);
1102
1103    if (opcode[inst->header.opcode].nsrc == 3) {
1104       pad (file, 16);
1105       err |= dest_3src (file, inst);
1106
1107       pad (file, 32);
1108       err |= src0_3src (file, inst);
1109
1110       pad (file, 48);
1111       err |= src1_3src (file, inst);
1112
1113       pad (file, 64);
1114       err |= src2_3src (file, inst);
1115    } else {
1116       if (opcode[inst->header.opcode].ndst > 0) {
1117	  pad (file, 16);
1118	  err |= dest (file, inst);
1119       } else if (gen >= 6 && (inst->header.opcode == BRW_OPCODE_IF ||
1120			       inst->header.opcode == BRW_OPCODE_ELSE ||
1121			       inst->header.opcode == BRW_OPCODE_ENDIF ||
1122			       inst->header.opcode == BRW_OPCODE_WHILE)) {
1123	  format (file, " %d", inst->bits1.branch_gen6.jump_count);
1124       } else if (gen >= 6 && (inst->header.opcode == BRW_OPCODE_BREAK ||
1125			       inst->header.opcode == BRW_OPCODE_CONTINUE ||
1126			       inst->header.opcode == BRW_OPCODE_HALT)) {
1127	  format (file, " %d %d", inst->bits3.break_cont.uip, inst->bits3.break_cont.jip);
1128       } else if (inst->header.opcode == BRW_OPCODE_JMPI) {
1129	  format (file, " %d", inst->bits3.d);
1130       }
1131
1132       if (opcode[inst->header.opcode].nsrc > 0) {
1133	  pad (file, 32);
1134	  err |= src0 (file, inst);
1135       }
1136       if (opcode[inst->header.opcode].nsrc > 1) {
1137	  pad (file, 48);
1138	  err |= src1 (file, inst);
1139       }
1140    }
1141
1142    if (inst->header.opcode == BRW_OPCODE_SEND ||
1143	inst->header.opcode == BRW_OPCODE_SENDC) {
1144	enum brw_message_target target;
1145
1146	if (gen >= 6)
1147	    target = inst->header.destreg__conditionalmod;
1148	else if (gen == 5)
1149	    target = inst->bits2.send_gen5.sfid;
1150	else
1151	    target = inst->bits3.generic.msg_target;
1152
1153	newline (file);
1154	pad (file, 16);
1155	space = 0;
1156
1157	if (gen >= 6) {
1158	   err |= control (file, "target function", target_function_gen6,
1159			   target, &space);
1160	} else {
1161	   err |= control (file, "target function", target_function,
1162			   target, &space);
1163	}
1164
1165	switch (target) {
1166	case BRW_SFID_MATH:
1167	    err |= control (file, "math function", math_function,
1168			    inst->bits3.math.function, &space);
1169	    err |= control (file, "math saturate", math_saturate,
1170			    inst->bits3.math.saturate, &space);
1171	    err |= control (file, "math signed", math_signed,
1172			    inst->bits3.math.int_type, &space);
1173	    err |= control (file, "math scalar", math_scalar,
1174			    inst->bits3.math.data_type, &space);
1175	    err |= control (file, "math precision", math_precision,
1176			    inst->bits3.math.precision, &space);
1177	    break;
1178	case BRW_SFID_SAMPLER:
1179	    if (gen >= 7) {
1180		format (file, " (%d, %d, %d, %d)",
1181			inst->bits3.sampler_gen7.binding_table_index,
1182			inst->bits3.sampler_gen7.sampler,
1183			inst->bits3.sampler_gen7.msg_type,
1184			inst->bits3.sampler_gen7.simd_mode);
1185	    } else if (gen >= 5) {
1186		format (file, " (%d, %d, %d, %d)",
1187			inst->bits3.sampler_gen5.binding_table_index,
1188			inst->bits3.sampler_gen5.sampler,
1189			inst->bits3.sampler_gen5.msg_type,
1190			inst->bits3.sampler_gen5.simd_mode);
1191	    } else if (0 /* FINISHME: is_g4x */) {
1192		format (file, " (%d, %d)",
1193			inst->bits3.sampler_g4x.binding_table_index,
1194			inst->bits3.sampler_g4x.sampler);
1195	    } else {
1196		format (file, " (%d, %d, ",
1197			inst->bits3.sampler.binding_table_index,
1198			inst->bits3.sampler.sampler);
1199		err |= control (file, "sampler target format",
1200				sampler_target_format,
1201				inst->bits3.sampler.return_format, NULL);
1202		string (file, ")");
1203	    }
1204	    break;
1205	case BRW_SFID_DATAPORT_READ:
1206	    if (gen >= 6) {
1207		format (file, " (%d, %d, %d, %d)",
1208			inst->bits3.gen6_dp.binding_table_index,
1209			inst->bits3.gen6_dp.msg_control,
1210			inst->bits3.gen6_dp.msg_type,
1211			inst->bits3.gen6_dp.send_commit_msg);
1212	    } else if (gen >= 5 /* FINISHME: || is_g4x */) {
1213		format (file, " (%d, %d, %d)",
1214			inst->bits3.dp_read_gen5.binding_table_index,
1215			inst->bits3.dp_read_gen5.msg_control,
1216			inst->bits3.dp_read_gen5.msg_type);
1217	    } else {
1218		format (file, " (%d, %d, %d)",
1219			inst->bits3.dp_read.binding_table_index,
1220			inst->bits3.dp_read.msg_control,
1221			inst->bits3.dp_read.msg_type);
1222	    }
1223	    break;
1224
1225	case BRW_SFID_DATAPORT_WRITE:
1226	    if (gen >= 7) {
1227		format (file, " (");
1228
1229		err |= control (file, "DP rc message type",
1230				dp_rc_msg_type_gen6,
1231				inst->bits3.gen7_dp.msg_type, &space);
1232
1233		format (file, ", %d, %d, %d)",
1234			inst->bits3.gen7_dp.binding_table_index,
1235			inst->bits3.gen7_dp.msg_control,
1236			inst->bits3.gen7_dp.msg_type);
1237	    } else if (gen == 6) {
1238		format (file, " (");
1239
1240		err |= control (file, "DP rc message type",
1241				dp_rc_msg_type_gen6,
1242				inst->bits3.gen6_dp.msg_type, &space);
1243
1244		format (file, ", %d, %d, %d, %d)",
1245			inst->bits3.gen6_dp.binding_table_index,
1246			inst->bits3.gen6_dp.msg_control,
1247			inst->bits3.gen6_dp.msg_type,
1248			inst->bits3.gen6_dp.send_commit_msg);
1249	    } else {
1250		format (file, " (%d, %d, %d, %d)",
1251			inst->bits3.dp_write.binding_table_index,
1252			(inst->bits3.dp_write.last_render_target << 3) |
1253			inst->bits3.dp_write.msg_control,
1254			inst->bits3.dp_write.msg_type,
1255			inst->bits3.dp_write.send_commit_msg);
1256	    }
1257	    break;
1258
1259	case BRW_SFID_URB:
1260	    if (gen >= 5) {
1261		format (file, " %d", inst->bits3.urb_gen5.offset);
1262	    } else {
1263		format (file, " %d", inst->bits3.urb.offset);
1264	    }
1265
1266	    space = 1;
1267	    if (gen >= 5) {
1268		err |= control (file, "urb opcode", urb_opcode,
1269				inst->bits3.urb_gen5.opcode, &space);
1270	    }
1271	    err |= control (file, "urb swizzle", urb_swizzle,
1272			    inst->bits3.urb.swizzle_control, &space);
1273	    err |= control (file, "urb allocate", urb_allocate,
1274			    inst->bits3.urb.allocate, &space);
1275	    err |= control (file, "urb used", urb_used,
1276			    inst->bits3.urb.used, &space);
1277	    err |= control (file, "urb complete", urb_complete,
1278			    inst->bits3.urb.complete, &space);
1279	    break;
1280	case BRW_SFID_THREAD_SPAWNER:
1281	    break;
1282	case GEN7_SFID_DATAPORT_DATA_CACHE:
1283	    format (file, " (%d, %d, %d)",
1284		    inst->bits3.gen7_dp.binding_table_index,
1285		    inst->bits3.gen7_dp.msg_control,
1286		    inst->bits3.gen7_dp.msg_type);
1287	    break;
1288
1289
1290	default:
1291	    format (file, "unsupported target %d", target);
1292	    break;
1293	}
1294	if (space)
1295	    string (file, " ");
1296	if (gen >= 5) {
1297	   format (file, "mlen %d",
1298		   inst->bits3.generic_gen5.msg_length);
1299	   format (file, " rlen %d",
1300		   inst->bits3.generic_gen5.response_length);
1301	} else {
1302	   format (file, "mlen %d",
1303		   inst->bits3.generic.msg_length);
1304	   format (file, " rlen %d",
1305		   inst->bits3.generic.response_length);
1306	}
1307    }
1308    pad (file, 64);
1309    if (inst->header.opcode != BRW_OPCODE_NOP) {
1310	string (file, "{");
1311	space = 1;
1312	err |= control(file, "access mode", access_mode, inst->header.access_mode, &space);
1313	if (gen >= 6)
1314	    err |= control (file, "write enable control", wectrl, inst->header.mask_control, &space);
1315	else
1316	    err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space);
1317	err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space);
1318
1319	if (gen >= 6)
1320	    err |= qtr_ctrl (file, inst);
1321	else {
1322	    if (inst->header.compression_control == BRW_COMPRESSION_COMPRESSED &&
1323		opcode[inst->header.opcode].ndst > 0 &&
1324		inst->bits1.da1.dest_reg_file == BRW_MESSAGE_REGISTER_FILE &&
1325		inst->bits1.da1.dest_reg_nr & (1 << 7)) {
1326		format (file, " compr4");
1327	    } else {
1328		err |= control (file, "compression control", compr_ctrl,
1329				inst->header.compression_control, &space);
1330	    }
1331	}
1332
1333	err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space);
1334	if (gen >= 6)
1335	    err |= control (file, "acc write control", accwr, inst->header.acc_wr_control, &space);
1336	if (inst->header.opcode == BRW_OPCODE_SEND ||
1337	    inst->header.opcode == BRW_OPCODE_SENDC)
1338	    err |= control (file, "end of thread", end_of_thread,
1339			    inst->bits3.generic.end_of_thread, &space);
1340	if (space)
1341	    string (file, " ");
1342	string (file, "}");
1343    }
1344    string (file, ";");
1345    newline (file);
1346    return err;
1347}
1348