tests: remove unused getopt header includes
[platform/upstream/intel-gpu-tools.git] / assembler / gen8_disasm.c
1 /*
2  * Copyright © 2013 Intel Corporation
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 "brw_context.h"
31 #include "brw_defines.h"
32 #include "gen8_instruction.h"
33
34 static const struct opcode_desc *m_opcode = opcode_descs;
35
36 static const char *const m_conditional_modifier[16] = {
37    /* [0 - BRW_CONDITIONAL_NONE] */ "",
38    /* [1 - BRW_CONDITIONAL_Z]    */ ".e",
39    /* [2 - BRW_CONDITIONAL_NZ]   */ ".ne",
40    /* [3 - BRW_CONDITIONAL_G]    */ ".g",
41    /* [4 - BRW_CONDITIONAL_GE]   */ ".ge",
42    /* [5 - BRW_CONDITIONAL_L]    */ ".l",
43    /* [6 - BRW_CONDITIONAL_LE]   */ ".le",
44    /* [7 - Reserved]             */ NULL,
45    /* [8 - BRW_CONDITIONAL_O]    */ ".o",
46    /* [9 - BRW_CONDITIONAL_U]    */ ".u",
47    /* [a-f - Reserved]           */
48 };
49
50 static const char *const m_negate[2] = { "", "-" };
51
52 static const char *const m_abs[2] = { "", "(abs)" };
53
54 static const char *const m_vert_stride[16] = {
55    "0",
56    "1",
57    "2",
58    "4",
59    "8",
60    "16",
61    "32",
62 };
63
64 static const char *const width[8] = {
65    "1",
66    "2",
67    "4",
68    "8",
69    "16",
70 };
71
72 static const char *const m_horiz_stride[4] = {
73    "0",
74    "1",
75    "2",
76    "4"
77 };
78
79 static const char *const m_chan_sel[4] = { "x", "y", "z", "w" };
80
81 static const char *const m_debug_ctrl[2] = { "", ".breakpoint" };
82
83 static const char *const m_saturate[2] = { "", ".sat" };
84
85 static const char *const m_accwr[2] = { "", "AccWrEnable" };
86
87 static const char *const m_maskctrl[2] = { "WE_normal", "WE_all" };
88
89 static const char *const m_exec_size[8] = {
90    "1",
91    "2",
92    "4",
93    "8",
94    "16",
95    "32",
96 };
97
98 static const char *const m_pred_inv[2] = { "+", "-" };
99
100 static const char *const m_pred_ctrl_align16[16] = {
101    "",
102    "",
103    ".x",
104    ".y",
105    ".z",
106    ".w",
107    ".any4h",
108    ".all4h",
109 };
110
111 static const char *const m_pred_ctrl_align1[16] = {
112    "",
113    "",
114    ".anyv",
115    ".allv",
116    ".any2h",
117    ".all2h",
118    ".any4h",
119    ".all4h",
120    ".any8h",
121    ".all8h",
122    ".any16h",
123    ".all16h",
124    ".any32h",
125    ".all32h",
126 };
127
128 static const char *const m_thread_ctrl[4] = {
129    "",
130    "atomic",
131    "switch",
132 };
133
134 static const char *const m_dep_ctrl[4] = {
135    "",
136    "NoDDClr",
137    "NoDDChk",
138    "NoDDClr,NoDDChk",
139 };
140
141 static const char *const m_mask_ctrl[4] = {
142    "",
143    "nomask",
144 };
145
146 static const char *const m_access_mode[2] = { "align1", "align16" };
147
148 static const char *const m_reg_type[8] = {
149    "UD",
150    "D",
151    "UW",
152    "W",
153    "UB",
154    "B",
155    "DF",
156    "F",
157 };
158
159 static const int reg_type_size[8] = {
160    /* UD */ 4,
161    /* D  */ 4,
162    /* UW */ 2,
163    /* W  */ 2,
164    /* UB */ 1,
165    /* B  */ 1,
166    /* DF */ 8,
167    /* F  */ 4,
168 };
169
170 static const char *const m_reg_file[4] = {
171    "A",
172    "g",
173    NULL,
174    "imm",
175 };
176
177 static const char *const m_writemask[16] = {
178    ".(none)",
179    ".x",
180    ".y",
181    ".xy",
182    ".z",
183    ".xz",
184    ".yz",
185    ".xyz",
186    ".w",
187    ".xw",
188    ".yw",
189    ".xyw",
190    ".zw",
191    ".xzw",
192    ".yzw",
193    "",
194 };
195
196 static const char *const m_eot[2] = { "", "EOT" };
197
198 static const char *const m_sfid[16] = {
199    /* [0 - BRW_SFID_NULL] */                     "null",
200    /* [1 - Reserved] */                          NULL,
201    /* [2 - BRW_SFID_SAMPLER] */                  "sampler",
202    /* [3 - BRW_SFID_MESSAGE_GATEWAY] */          "gateway",
203    /* [4 - GEN6_SFID_DATAPORT_SAMPLER_CACHE] */  "dp/sampler_cache",
204    /* [5 - GEN6_SFID_DATAPORT_RENDER_CACHE] */   "dp/render_cache",
205    /* [6 - BRW_SFID_URB] */                      "URB",
206    /* [7 - BRW_SFID_THREAD_SPAWNER] */           "thread_spawner",
207    /* [8 - BRW_SFID_VME] */                      "vme",
208    /* [9 - GEN6_SFID_DATAPORT_CONSTANT_CACHE] */ "dp/constant_cache",
209    /* [a - GEN7_SFID_DATAPORT_DATA_CACHE] */     "dp/data_cache",
210    /* [b - GEN7_SFID_PI] */                      "pi",
211    /* [c - HSW_SFID_DATAPORT_DATA_CACHE_1] */    "dp/data_cache:1",
212    /* [d - HSW_SFID_CRE] */                      "cre",
213    /* [e-f - Reserved */                         NULL, NULL,
214 };
215
216 #if 0
217 static const char *const dp_rc_msg_type[16] = {
218    [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
219    [GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
220    [GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
221    [GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read",
222    [GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] = "OWORD unaligned block read",
223    [GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read",
224    [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write",
225    [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write",
226    [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] = "OWORD dual block write",
227    [GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write",
228    [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] = "DWORD scattered write",
229    [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write",
230    [GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write",
231    [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORMc write",
232 };
233 #endif
234
235 static const char *const m_math_function[16] = {
236    /* [0 - Reserved]                                         */ NULL,
237    /* [1 - BRW_MATH_FUNCTION_INV]                            */ "inv",
238    /* [2 - BRW_MATH_FUNCTION_LOG]                            */ "log",
239    /* [3 - BRW_MATH_FUNCTION_EXP]                            */ "exp",
240    /* [4 - BRW_MATH_FUNCTION_SQRT]                           */ "sqrt",
241    /* [5 - BRW_MATH_FUNCTION_RSQ]                            */ "rsq",
242    /* [6 - BRW_MATH_FUNCTION_SIN]                            */ "sin",
243    /* [7 - BRW_MATH_FUNCTION_COS]                            */ "cos",
244    /* [8 - Reserved]                                         */ NULL,
245    /* [9 - BRW_MATH_FUNCTION_FDIV]                           */ "fdiv",
246    /* [a - BRW_MATH_FUNCTION_POW]                            */ "pow",
247    /* [b - BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] */ "intdivmod",
248    /* [c - BRW_MATH_FUNCTION_INT_DIV_QUOTIENT]               */ "intdiv",
249    /* [d - BRW_MATH_FUNCTION_INT_DIV_REMAINDER]              */ "intmod",
250    /* [e - GEN8_MATH_FUNCTION_INVM]                          */ "invm",
251    /* [f - GEN8_MATH_FUNCTION_RSQRTM]                        */ "rsqrtm",
252 };
253
254 static const char *const m_urb_opcode[16] = {
255    /* [0] */ "write HWord",
256    /* [1] */ "write OWord",
257    /* [2] */ "read HWord",
258    /* [3] */ "read OWord",
259    /* [4] */ "atomic mov",
260    /* [5] */ "atomic inc",
261    /* [6] */ "atomic add",
262    /* [7] */ "SIMD8 write",
263    /* [8] */ "SIMD8 read",
264    /* [9-15] - reserved */
265 };
266
267 static const char *const m_urb_interleave[2] = { "", "interleaved" };
268
269 static int column;
270
271 static int
272 string(FILE *file, const char *string)
273 {
274    fputs(string, file);
275    column += strlen(string);
276    return 0;
277 }
278
279 static int
280 format(FILE *f, const char *format, ...)
281 {
282    char buf[1024];
283    va_list args;
284    va_start(args, format);
285
286    vsnprintf(buf, sizeof(buf) - 1, format, args);
287    va_end(args);
288    string(f, buf);
289    return 0;
290 }
291
292 static int
293 newline(FILE *f)
294 {
295    putc('\n', f);
296    column = 0;
297    return 0;
298 }
299
300 static int
301 pad(FILE *f, int c)
302 {
303    do
304       string(f, " ");
305    while (column < c);
306    return 0;
307 }
308
309 static int
310 control(FILE *file, const char *name, const char *const ctrl[],
311         unsigned id, int *space)
312 {
313    if (!ctrl[id]) {
314       fprintf(file, "*** invalid %s value %d ", name, id);
315       return 1;
316    }
317    if (ctrl[id][0])
318    {
319       if (space && *space)
320          string(file, " ");
321       string(file, ctrl[id]);
322       if (space)
323          *space = 1;
324    }
325    return 0;
326 }
327
328 static int
329 print_opcode(FILE *file, int id)
330 {
331    if (!m_opcode[id].name) {
332       format(file, "*** invalid opcode value %d ", id);
333       return 1;
334    }
335    string(file, m_opcode[id].name);
336    return 0;
337 }
338
339 static int
340 reg(FILE *file, unsigned reg_file, unsigned _reg_nr)
341 {
342    int err = 0;
343
344    if (reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
345       switch (_reg_nr & 0xf0) {
346       case BRW_ARF_NULL:
347          string(file, "null");
348          return -1;
349       case BRW_ARF_ADDRESS:
350          format(file, "a%d", _reg_nr & 0x0f);
351          break;
352       case BRW_ARF_ACCUMULATOR:
353          format(file, "acc%d", _reg_nr & 0x0f);
354          break;
355       case BRW_ARF_FLAG:
356          format(file, "f%d", _reg_nr & 0x0f);
357          break;
358       case BRW_ARF_MASK:
359          format(file, "mask%d", _reg_nr & 0x0f);
360          break;
361       case BRW_ARF_MASK_STACK:
362          format(file, "msd%d", _reg_nr & 0x0f);
363          break;
364       case BRW_ARF_STATE:
365          format(file, "sr%d", _reg_nr & 0x0f);
366          break;
367       case BRW_ARF_CONTROL:
368          format(file, "cr%d", _reg_nr & 0x0f);
369          break;
370       case BRW_ARF_NOTIFICATION_COUNT:
371          format(file, "n%d", _reg_nr & 0x0f);
372          break;
373       case BRW_ARF_IP:
374          string(file, "ip");
375          return -1;
376          break;
377       default:
378          format(file, "ARF%d", _reg_nr);
379          break;
380       }
381    } else {
382       err |= control(file, "src reg file", m_reg_file, reg_file, NULL);
383       format(file, "%d", _reg_nr);
384    }
385    return err;
386 }
387
388 static int
389 dest(FILE *file, struct gen8_instruction *inst)
390 {
391    int err = 0;
392
393    if (gen8_access_mode(inst) == BRW_ALIGN_1)
394    {
395       assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
396       err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
397       if (err == -1)
398          return 0;
399       if (gen8_dst_da1_subreg_nr(inst))
400          format(file, ".%d", gen8_dst_da1_subreg_nr(inst) /
401                 reg_type_size[gen8_dst_reg_type(inst)]);
402       string(file, "<");
403       err |= control(file, "horiz stride", m_horiz_stride, gen8_dst_da1_hstride(inst), NULL);
404       string(file, ">");
405       err |= control(file, "dest reg encoding", m_reg_type, gen8_dst_reg_type(inst), NULL);
406    }
407    else
408    {
409       assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
410       err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
411       if (err == -1)
412          return 0;
413       if (gen8_dst_da16_subreg_nr(inst))
414          format(file, ".%d", gen8_dst_da16_subreg_nr(inst) /
415                 reg_type_size[gen8_dst_reg_type(inst)]);
416       string(file, "<1>");
417       err |= control(file, "writemask", m_writemask, gen8_da16_writemask(inst), NULL);
418       err |= control(file, "dest reg encoding", m_reg_type, gen8_dst_reg_type(inst), NULL);
419    }
420
421    return 0;
422 }
423
424 #if 0
425 static int
426 dest_3src(FILE *file, gen8_instruction *inst)
427 {
428    int      err = 0;
429    uint32_t reg_file;
430
431    if (inst->bits1.da3src.dest_reg_file)
432       reg_file = BRW_MESSAGE_REGISTER_FILE;
433    else
434       reg_file = BRW_GENERAL_REGISTER_FILE;
435
436    err |= reg(file, reg_file, inst->bits1.da3src.dest_reg_nr);
437    if (err == -1)
438       return 0;
439    if (inst->bits1.da3src.dest_subreg_nr)
440       format(file, ".%d", inst->bits1.da3src.dest_subreg_nr);
441    string(file, "<1>");
442    err |= control(file, "writemask", m_writemask, inst->bits1.da3src.dest_writemask, NULL);
443    err |= control(file, "dest reg encoding", m_reg_type, BRW_REGISTER_TYPE_F, NULL);
444
445    return 0;
446 }
447 #endif
448
449 static int
450 src_align1_region(FILE *file, unsigned vert_stride, unsigned _width,
451                   unsigned horiz_stride)
452 {
453    int err = 0;
454    string(file, "<");
455    err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
456    string(file, ",");
457    err |= control(file, "width", width, _width, NULL);
458    string(file, ",");
459    err |= control(file, "horiz_stride", m_horiz_stride, horiz_stride, NULL);
460    string(file, ">");
461    return err;
462 }
463
464 static int
465 src_da1(FILE *file, unsigned type, unsigned reg_file,
466         unsigned vert_stride, unsigned _width, unsigned horiz_stride,
467         unsigned reg_num, unsigned sub_reg_num, unsigned _abs, unsigned negate)
468 {
469    int err = 0;
470    err |= control(file, "negate", m_negate, negate, NULL);
471    err |= control(file, "abs", m_abs, _abs, NULL);
472
473    err |= reg(file, reg_file, reg_num);
474    if (err == -1)
475       return 0;
476    if (sub_reg_num)
477       format(file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
478    src_align1_region(file, vert_stride, _width, horiz_stride);
479    err |= control(file, "src reg encoding", m_reg_type, type, NULL);
480    return err;
481 }
482
483 static int
484 src_da16(FILE *file,
485          unsigned _reg_type,
486          unsigned reg_file,
487          unsigned vert_stride,
488          unsigned _reg_nr,
489          unsigned _subreg_nr,
490          unsigned _abs,
491          unsigned negate,
492          unsigned swz_x,
493          unsigned swz_y,
494          unsigned swz_z,
495          unsigned swz_w)
496 {
497    int err = 0;
498    err |= control(file, "negate", m_negate, negate, NULL);
499    err |= control(file, "abs", m_abs, _abs, NULL);
500
501    err |= reg(file, reg_file, _reg_nr);
502    if (err == -1)
503       return 0;
504    if (_subreg_nr)
505       /* bit4 for subreg number byte addressing. Make this same meaning as
506          in da1 case, so output looks consistent. */
507       format(file, ".%d", 16 / reg_type_size[_reg_type]);
508    string(file, "<");
509    err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
510    string(file, ",4,1>");
511    /*
512     * Three kinds of swizzle display:
513     *  identity - nothing printed
514     *  1->all       - print the single channel
515     *  1->1    - print the mapping
516     */
517    if (swz_x == BRW_CHANNEL_X &&
518       swz_y == BRW_CHANNEL_Y &&
519       swz_z == BRW_CHANNEL_Z &&
520       swz_w == BRW_CHANNEL_W)
521    {
522       ;
523    }
524    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
525    {
526       string(file, ".");
527       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
528    }
529    else
530    {
531       string(file, ".");
532       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
533       err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
534       err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
535       err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
536    }
537    err |= control(file, "src da16 reg type", m_reg_type, _reg_type, NULL);
538    return err;
539 }
540
541 #if 0
542 static int
543 src0_3src(FILE *file, gen8_instruction *inst)
544 {
545    int err = 0;
546    unsigned swz_x = (inst->bits2.da3src.src0_swizzle >> 0) & 0x3;
547    unsigned swz_y = (inst->bits2.da3src.src0_swizzle >> 2) & 0x3;
548    unsigned swz_z = (inst->bits2.da3src.src0_swizzle >> 4) & 0x3;
549    unsigned swz_w = (inst->bits2.da3src.src0_swizzle >> 6) & 0x3;
550
551    err |= control(file, "negate", m_negate, inst->bits1.da3src.src0_negate, NULL);
552    err |= control(file, "abs", m_abs, inst->bits1.da3src.src0_abs, NULL);
553
554    err |= reg(file, BRW_GENERAL_REGISTER_FILE, inst->bits2.da3src.src0_reg_nr);
555    if (err == -1)
556       return 0;
557    if (inst->bits2.da3src.src0_subreg_nr)
558       format(file, ".%d", inst->bits2.da3src.src0_subreg_nr);
559    string(file, "<4,1,1>");
560    err |= control(file, "src da16 reg type", m_reg_type,
561                BRW_REGISTER_TYPE_F, NULL);
562    /*
563     * Three kinds of swizzle display:
564     *  identity - nothing printed
565     *  1->all       - print the single channel
566     *  1->1    - print the mapping
567     */
568    if (swz_x == BRW_CHANNEL_X &&
569       swz_y == BRW_CHANNEL_Y &&
570       swz_z == BRW_CHANNEL_Z &&
571       swz_w == BRW_CHANNEL_W)
572    {
573       ;
574    }
575    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
576    {
577       string(file, ".");
578       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
579    }
580    else
581    {
582       string(file, ".");
583       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
584       err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
585       err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
586       err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
587    }
588    return err;
589 }
590
591 static int
592 src1_3src(FILE *file, gen8_instruction *inst)
593 {
594    int err = 0;
595    unsigned swz_x = (inst->bits2.da3src.src1_swizzle >> 0) & 0x3;
596    unsigned swz_y = (inst->bits2.da3src.src1_swizzle >> 2) & 0x3;
597    unsigned swz_z = (inst->bits2.da3src.src1_swizzle >> 4) & 0x3;
598    unsigned swz_w = (inst->bits2.da3src.src1_swizzle >> 6) & 0x3;
599    unsigned src1_subreg_nr = (inst->bits2.da3src.src1_subreg_nr_low |
600                       (inst->bits3.da3src.src1_subreg_nr_high << 2));
601
602    err |= control(file, "negate", m_negate, inst->bits1.da3src.src1_negate,
603                NULL);
604    err |= control(file, "abs", m_abs, inst->bits1.da3src.src1_abs, NULL);
605
606    err |= reg(file, BRW_GENERAL_REGISTER_FILE,
607             inst->bits3.da3src.src1_reg_nr);
608    if (err == -1)
609       return 0;
610    if (src1_subreg_nr)
611       format(file, ".%d", src1_subreg_nr);
612    string(file, "<4,1,1>");
613    err |= control(file, "src da16 reg type", m_reg_type,
614                BRW_REGISTER_TYPE_F, NULL);
615    /*
616     * Three kinds of swizzle display:
617     *  identity - nothing printed
618     *  1->all       - print the single channel
619     *  1->1    - print the mapping
620     */
621    if (swz_x == BRW_CHANNEL_X &&
622       swz_y == BRW_CHANNEL_Y &&
623       swz_z == BRW_CHANNEL_Z &&
624       swz_w == BRW_CHANNEL_W)
625    {
626       ;
627    }
628    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
629    {
630       string(file, ".");
631       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
632    }
633    else
634    {
635       string(file, ".");
636       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
637       err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
638       err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
639       err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
640    }
641    return err;
642 }
643
644
645 static int
646 src2_3src(FILE *file, gen8_instruction *inst)
647 {
648    int err = 0;
649    unsigned swz_x = (inst->bits3.da3src.src2_swizzle >> 0) & 0x3;
650    unsigned swz_y = (inst->bits3.da3src.src2_swizzle >> 2) & 0x3;
651    unsigned swz_z = (inst->bits3.da3src.src2_swizzle >> 4) & 0x3;
652    unsigned swz_w = (inst->bits3.da3src.src2_swizzle >> 6) & 0x3;
653
654    err |= control(file, "negate", m_negate, inst->bits1.da3src.src2_negate,
655                NULL);
656    err |= control(file, "abs", m_abs, inst->bits1.da3src.src2_abs, NULL);
657
658    err |= reg(file, BRW_GENERAL_REGISTER_FILE,
659             inst->bits3.da3src.src2_reg_nr);
660    if (err == -1)
661       return 0;
662    if (inst->bits3.da3src.src2_subreg_nr)
663       format(file, ".%d", inst->bits3.da3src.src2_subreg_nr);
664    string(file, "<4,1,1>");
665    err |= control(file, "src da16 reg type", m_reg_type,
666                BRW_REGISTER_TYPE_F, NULL);
667    /*
668     * Three kinds of swizzle display:
669     *  identity - nothing printed
670     *  1->all       - print the single channel
671     *  1->1    - print the mapping
672     */
673    if (swz_x == BRW_CHANNEL_X &&
674       swz_y == BRW_CHANNEL_Y &&
675       swz_z == BRW_CHANNEL_Z &&
676       swz_w == BRW_CHANNEL_W)
677    {
678       ;
679    }
680    else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
681    {
682       string(file, ".");
683       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
684    }
685    else
686    {
687       string(file, ".");
688       err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
689       err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
690       err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
691       err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
692    }
693    return err;
694 }
695 #endif
696
697 static int
698 imm(FILE *file, unsigned type, struct gen8_instruction *inst)
699 {
700    switch (type) {
701    case BRW_REGISTER_TYPE_UD:
702       format(file, "0x%08xUD", gen8_src1_imm_ud(inst));
703       break;
704    case BRW_REGISTER_TYPE_D:
705       format(file, "%dD", (int) gen8_src1_imm_d(inst));
706       break;
707    case BRW_REGISTER_TYPE_UW:
708       format(file, "0x%04xUW", (uint16_t) gen8_src1_imm_ud(inst));
709       break;
710    case BRW_REGISTER_TYPE_W:
711       format(file, "%dW", (int16_t) gen8_src1_imm_d(inst));
712       break;
713    case BRW_REGISTER_TYPE_UB:
714       format(file, "0x%02xUB", (int8_t) gen8_src1_imm_ud(inst));
715       break;
716    case BRW_REGISTER_TYPE_VF:
717       format(file, "Vector Float");
718       break;
719    case BRW_REGISTER_TYPE_V:
720       format(file, "0x%08xV", gen8_src1_imm_ud(inst));
721       break;
722    case BRW_REGISTER_TYPE_F:
723       format(file, "%-gF", gen8_src1_imm_f(inst));
724    }
725    return 0;
726 }
727
728 static int
729 src0(FILE *file, struct gen8_instruction *inst)
730 {
731    if (gen8_src0_reg_file(inst) == BRW_IMMEDIATE_VALUE)
732       return imm(file, gen8_src0_reg_type(inst), inst);
733
734    if (gen8_access_mode(inst) == BRW_ALIGN_1)
735    {
736       assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
737       return src_da1(file,
738                      gen8_src0_reg_type(inst),
739                      gen8_src0_reg_file(inst),
740                      gen8_src0_vert_stride(inst),
741                      gen8_src0_da1_width(inst),
742                      gen8_src0_da1_hstride(inst),
743                      gen8_src0_da_reg_nr(inst),
744                      gen8_src0_da1_subreg_nr(inst),
745                      gen8_src0_abs(inst),
746                      gen8_src0_negate(inst));
747    }
748    else
749    {
750       assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
751       return src_da16(file,
752                       gen8_src0_reg_type(inst),
753                       gen8_src0_reg_file(inst),
754                       gen8_src0_vert_stride(inst),
755                       gen8_src0_da_reg_nr(inst),
756                       gen8_src0_da16_subreg_nr(inst),
757                       gen8_src0_abs(inst),
758                       gen8_src0_negate(inst),
759                       gen8_src0_da16_swiz_x(inst),
760                       gen8_src0_da16_swiz_y(inst),
761                       gen8_src0_da16_swiz_z(inst),
762                       gen8_src0_da16_swiz_w(inst));
763    }
764 }
765
766 static int
767 src1(FILE *file, struct gen8_instruction *inst)
768 {
769    if (gen8_src1_reg_file(inst) == BRW_IMMEDIATE_VALUE)
770       return imm(file, gen8_src1_reg_type(inst), inst);
771
772    if (gen8_access_mode(inst) == BRW_ALIGN_1)
773    {
774       assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
775       return src_da1(file,
776                      gen8_src1_reg_type(inst),
777                      gen8_src1_reg_file(inst),
778                      gen8_src1_vert_stride(inst),
779                      gen8_src1_da1_width(inst),
780                      gen8_src1_da1_hstride(inst),
781                      gen8_src1_da_reg_nr(inst),
782                      gen8_src1_da1_subreg_nr(inst),
783                      gen8_src1_abs(inst),
784                      gen8_src1_negate(inst));
785    }
786    else
787    {
788       assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
789       return src_da16(file,
790                       gen8_src1_reg_type(inst),
791                       gen8_src1_reg_file(inst),
792                       gen8_src1_vert_stride(inst),
793                       gen8_src1_da_reg_nr(inst),
794                       gen8_src1_da16_subreg_nr(inst),
795                       gen8_src1_abs(inst),
796                       gen8_src1_negate(inst),
797                       gen8_src1_da16_swiz_x(inst),
798                       gen8_src1_da16_swiz_y(inst),
799                       gen8_src1_da16_swiz_z(inst),
800                       gen8_src1_da16_swiz_w(inst));
801    }
802 }
803
804 static int esize[6] = { 1, 2, 4, 8, 16, 32 };
805
806 static int
807 qtr_ctrl(FILE *file, struct gen8_instruction *inst)
808 {
809    int qtr_ctl = gen8_qtr_control(inst);
810    int exec_size = esize[gen8_exec_size(inst)];
811
812    if (exec_size == 8) {
813       switch (qtr_ctl) {
814       case 0:
815          string(file, " 1Q");
816          break;
817       case 1:
818          string(file, " 2Q");
819          break;
820       case 2:
821          string(file, " 3Q");
822          break;
823       case 3:
824          string(file, " 4Q");
825          break;
826       }
827    } else if (exec_size == 16) {
828       if (qtr_ctl < 2)
829          string(file, " 1H");
830       else
831          string(file, " 2H");
832    }
833    return 0;
834 }
835
836 int
837 gen8_disassemble(FILE *file, struct gen8_instruction *insn, int gen)
838 {
839    int err = 0;
840    int space = 0;
841
842    const int opcode = gen8_opcode(insn);
843
844    if (gen8_pred_control(insn)) {
845       string(file, "(");
846       err |= control(file, "predicate inverse", m_pred_inv, gen8_pred_inv(insn), NULL);
847       format(file, "f%d", gen8_flag_reg_nr(insn));
848       if (gen8_flag_subreg_nr(insn))
849          format(file, ".%d", gen8_flag_subreg_nr(insn));
850       if (gen8_access_mode(insn) == BRW_ALIGN_1) {
851          err |= control(file, "predicate control align1", m_pred_ctrl_align1,
852                         gen8_pred_control(insn), NULL);
853       } else {
854          err |= control(file, "predicate control align16", m_pred_ctrl_align16,
855                         gen8_pred_control(insn), NULL);
856       }
857       string(file, ") ");
858    }
859
860    err |= print_opcode(file, opcode);
861    err |= control(file, "saturate", m_saturate, gen8_saturate(insn), NULL);
862    err |= control(file, "debug control", m_debug_ctrl, gen8_debug_control(insn), NULL);
863
864    if (opcode == BRW_OPCODE_MATH) {
865       string(file, " ");
866       err |= control(file, "function", m_math_function, gen8_math_function(insn),
867                      NULL);
868    } else if (opcode != BRW_OPCODE_SEND && opcode != BRW_OPCODE_SENDC) {
869       err |= control(file, "conditional modifier", m_conditional_modifier,
870                      gen8_cond_modifier(insn), NULL);
871
872       /* If we're using the conditional modifier, print the flag reg used. */
873       if (gen8_cond_modifier(insn) && opcode != BRW_OPCODE_SEL) {
874          format(file, ".f%d", gen8_flag_reg_nr(insn));
875          if (gen8_flag_subreg_nr(insn))
876             format(file, ".%d", gen8_flag_subreg_nr(insn));
877       }
878    }
879
880    if (opcode != BRW_OPCODE_NOP) {
881       string(file, "(");
882       err |= control(file, "execution size", m_exec_size, gen8_exec_size(insn), NULL);
883       string(file, ")");
884    }
885
886    if (m_opcode[opcode].nsrc == 3) {
887       string(file, "XXX: 3-src");
888       #if 0
889       pad(file, 16);
890       err |= dest_3src(file, this);
891
892       pad(file, 32);
893       err |= src0_3src(file, this);
894
895       pad(file, 48);
896       err |= src1_3src(file, this);
897
898       pad(file, 64);
899       err |= src2_3src(file, this);
900       #endif
901    } else {
902       if (m_opcode[opcode].ndst > 0) {
903          pad(file, 16);
904          err |= dest(file, insn);
905       } else if (opcode == BRW_OPCODE_ENDIF) {
906          format(file, " %d", gen8_jip(insn));
907       } else if (opcode == BRW_OPCODE_IF ||
908                  opcode == BRW_OPCODE_ELSE ||
909                  opcode == BRW_OPCODE_WHILE ||
910                  opcode == BRW_OPCODE_BREAK ||
911                  opcode == BRW_OPCODE_CONTINUE ||
912                  opcode == BRW_OPCODE_HALT) {
913          format(file, " %d %d", gen8_jip(insn), gen8_uip(insn));
914       }
915
916       if (m_opcode[opcode].nsrc > 0) {
917          pad(file, 32);
918          err |= src0(file, insn);
919       }
920       if (m_opcode[opcode].nsrc > 1) {
921          pad(file, 48);
922          err |= src1(file, insn);
923       }
924    }
925
926    if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC) {
927       const int sfid = gen8_sfid(insn);
928
929       newline(file);
930       pad(file, 16);
931       space = 0;
932
933       err |= control(file, "SFID", m_sfid, sfid, &space);
934
935       switch (sfid) {
936       case BRW_SFID_SAMPLER:
937          format(file, " (%d, %d, %d, %d)",
938                 gen8_binding_table_index(insn),
939                 gen8_sampler(insn),
940                 gen8_sampler_msg_type(insn),
941                 gen8_sampler_simd_mode(insn));
942          break;
943
944       case BRW_SFID_URB:
945          space = 1;
946          err |= control(file, "urb opcode", m_urb_opcode,
947                         gen8_urb_opcode(insn), &space);
948          err |= control(file, "urb interleave", m_urb_interleave,
949                         gen8_urb_interleave(insn), &space);
950          format(file, " %d %d",
951                 gen8_urb_global_offset(insn), gen8_urb_per_slot_offset(insn));
952          break;
953
954       case GEN6_SFID_DATAPORT_SAMPLER_CACHE:
955       case GEN6_SFID_DATAPORT_RENDER_CACHE:
956       case GEN6_SFID_DATAPORT_CONSTANT_CACHE:
957       case GEN7_SFID_DATAPORT_DATA_CACHE:
958          format(file, " (%d, 0x%x)",
959                gen8_binding_table_index(insn),
960                gen8_function_control(insn));
961          break;
962
963       default:
964          format(file, "unsupported shared function ID (%d)", sfid);
965          break;
966       }
967       if (space)
968          string(file, " ");
969       format(file, "mlen %d", gen8_mlen(insn));
970       format(file, " rlen %d", gen8_rlen(insn));
971    }
972    pad(file, 64);
973    if (opcode != BRW_OPCODE_NOP) {
974       string(file, "{");
975       space = 1;
976       err |= control(file, "access mode", m_access_mode, gen8_access_mode(insn), &space);
977       err |= control(file, "mask control", m_maskctrl, gen8_mask_control(insn), &space);
978       err |= control(file, "dependency control", m_dep_ctrl, gen8_dep_control(insn), &space);
979
980       err |= qtr_ctrl(file, insn);
981
982       err |= control(file, "thread control", m_thread_ctrl, gen8_thread_control(insn), &space);
983       err |= control(file, "acc write control", m_accwr, gen8_acc_wr_control(insn), &space);
984       if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC)
985          err |= control(file, "end of thread", m_eot, gen8_eot(insn), &space);
986       if (space)
987          string(file, " ");
988       string(file, "}");
989    }
990    string(file, ";");
991    newline(file);
992    return err;
993 }