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