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