i965: Implement a disassembler for Broadwell's new instruction encoding.
[mesa.git] / src / mesa / drivers / dri / i965 / gen8_disasm.c
1 /*
2 * Copyright © 2008 Keith Packard
3 * Copyright © 2009-2013 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 * OF THIS SOFTWARE.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <getopt.h>
28 #include <unistd.h>
29 #include <stdarg.h>
30
31 #include "brw_context.h"
32 #include "brw_defines.h"
33 #include "gen8_instruction.h"
34
35 static const struct opcode_desc *m_opcode = opcode_descs;
36
37 static const char *const m_conditional_modifier[16] = {
38 [BRW_CONDITIONAL_NONE] = "",
39 [BRW_CONDITIONAL_Z] = ".e",
40 [BRW_CONDITIONAL_NZ] = ".ne",
41 [BRW_CONDITIONAL_G] = ".g",
42 [BRW_CONDITIONAL_GE] = ".ge",
43 [BRW_CONDITIONAL_L] = ".l",
44 [BRW_CONDITIONAL_LE] = ".le",
45 [BRW_CONDITIONAL_O] = ".o",
46 [BRW_CONDITIONAL_U] = ".u",
47 };
48
49 static const char *const m_negate[2] = { "", "-" };
50
51 static const char *const m_abs[2] = { "", "(abs)" };
52
53 static const char *const m_vert_stride[16] = {
54 "0",
55 "1",
56 "2",
57 "4",
58 "8",
59 "16",
60 "32",
61 };
62
63 static const char *const width[8] = {
64 "1",
65 "2",
66 "4",
67 "8",
68 "16",
69 };
70
71 static const char *const m_horiz_stride[4] = {
72 "0",
73 "1",
74 "2",
75 "4"
76 };
77
78 static const char *const m_chan_sel[4] = { "x", "y", "z", "w" };
79
80 static const char *const m_debug_ctrl[2] = { "", ".breakpoint" };
81
82 static const char *const m_saturate[2] = { "", ".sat" };
83
84 static const char *const m_accwr[2] = { "", "AccWrEnable" };
85
86 static const char *const m_maskctrl[2] = { "WE_normal", "WE_all" };
87
88 static const char *const m_exec_size[8] = {
89 "1",
90 "2",
91 "4",
92 "8",
93 "16",
94 "32",
95 };
96
97 static const char *const m_pred_inv[2] = { "+", "-" };
98
99 static const char *const m_pred_ctrl_align16[16] = {
100 "",
101 "",
102 ".x",
103 ".y",
104 ".z",
105 ".w",
106 ".any4h",
107 ".all4h",
108 };
109
110 static const char *const m_pred_ctrl_align1[16] = {
111 "",
112 "",
113 ".anyv",
114 ".allv",
115 ".any2h",
116 ".all2h",
117 ".any4h",
118 ".all4h",
119 ".any8h",
120 ".all8h",
121 ".any16h",
122 ".all16h",
123 ".any32h",
124 ".all32h",
125 };
126
127 static const char *const m_thread_ctrl[4] = {
128 "",
129 "atomic",
130 "switch",
131 };
132
133 static const char *const m_dep_clear[4] = {
134 "",
135 "NoDDClr",
136 };
137
138 static const char *const m_dep_check[4] = {
139 "",
140 "NoDDChk",
141 };
142
143 static const char *const m_mask_ctrl[4] = {
144 "",
145 "nomask",
146 };
147
148 static const char *const m_access_mode[2] = { "align1", "align16" };
149
150 static const char *const m_reg_encoding[] = {
151 [BRW_HW_REG_TYPE_UD] = "UD",
152 [BRW_HW_REG_TYPE_D] = "D",
153 [BRW_HW_REG_TYPE_UW] = "UW",
154 [BRW_HW_REG_TYPE_W] = "W",
155 [BRW_HW_REG_NON_IMM_TYPE_UB] = "UB",
156 [BRW_HW_REG_NON_IMM_TYPE_B] = "B",
157 [GEN7_HW_REG_NON_IMM_TYPE_DF] = "DF",
158 [BRW_HW_REG_TYPE_F] = "F",
159 [GEN8_HW_REG_TYPE_UQ] = "UQ",
160 [GEN8_HW_REG_TYPE_Q] = "Q",
161 [GEN8_HW_REG_NON_IMM_TYPE_HF] = "HF",
162 };
163
164 static const char *const m_three_source_reg_encoding[] = {
165 [BRW_3SRC_TYPE_F] = "F",
166 [BRW_3SRC_TYPE_D] = "D",
167 [BRW_3SRC_TYPE_UD] = "UD",
168 };
169
170 static const int reg_type_size[] = {
171 [BRW_HW_REG_TYPE_UD] = 4,
172 [BRW_HW_REG_TYPE_D] = 4,
173 [BRW_HW_REG_TYPE_UW] = 2,
174 [BRW_HW_REG_TYPE_W] = 2,
175 [BRW_HW_REG_NON_IMM_TYPE_UB] = 1,
176 [BRW_HW_REG_NON_IMM_TYPE_B] = 1,
177 [GEN7_HW_REG_NON_IMM_TYPE_DF] = 8,
178 [BRW_HW_REG_TYPE_F] = 4,
179 };
180
181 static const char *const m_reg_file[4] = {
182 [BRW_ARCHITECTURE_REGISTER_FILE] = "A",
183 [BRW_GENERAL_REGISTER_FILE] = "g",
184 [BRW_IMMEDIATE_VALUE] = "imm",
185 };
186
187 static const char *const m_writemask[16] = {
188 ".(none)",
189 ".x",
190 ".y",
191 ".xy",
192 ".z",
193 ".xz",
194 ".yz",
195 ".xyz",
196 ".w",
197 ".xw",
198 ".yw",
199 ".xyw",
200 ".zw",
201 ".xzw",
202 ".yzw",
203 "",
204 };
205
206 static const char *const m_eot[2] = { "", "EOT" };
207
208 static const char *const m_sfid[16] = {
209 [BRW_SFID_NULL] = "null",
210 [BRW_SFID_SAMPLER] = "sampler",
211 [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
212 [GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "dp/sampler_cache",
213 [GEN6_SFID_DATAPORT_RENDER_CACHE] = "dp/render_cache",
214 [BRW_SFID_URB] = "URB",
215 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner",
216 [BRW_SFID_VME] = "vme",
217 [GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "dp/constant_cache",
218 [GEN7_SFID_DATAPORT_DATA_CACHE] = "dp/data_cache",
219 [GEN7_SFID_PIXEL_INTERPOLATOR] = "pi",
220 [HSW_SFID_DATAPORT_DATA_CACHE_1] = "dp/data_cache:1",
221 [HSW_SFID_CRE] = "cre",
222 };
223
224 static const char *const m_math_function[16] = {
225 [BRW_MATH_FUNCTION_INV] = "inv",
226 [BRW_MATH_FUNCTION_LOG] = "log",
227 [BRW_MATH_FUNCTION_EXP] = "exp",
228 [BRW_MATH_FUNCTION_SQRT] = "sqrt",
229 [BRW_MATH_FUNCTION_RSQ] = "rsq",
230 [BRW_MATH_FUNCTION_SIN] = "sin",
231 [BRW_MATH_FUNCTION_COS] = "cos",
232 [BRW_MATH_FUNCTION_FDIV] = "fdiv",
233 [BRW_MATH_FUNCTION_POW] = "pow",
234 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
235 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
236 [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
237 [GEN8_MATH_FUNCTION_INVM] = "invm",
238 [GEN8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
239 };
240
241 static const char *const m_urb_opcode[16] = {
242 [0] = "write HWord",
243 [1] = "write OWord",
244 [2] = "read HWord",
245 [3] = "read OWord",
246 [4] = "atomic mov",
247 [5] = "atomic inc",
248 [6] = "atomic add",
249 [7] = "SIMD8 write",
250 [8] = "SIMD8 read",
251 /* [9-15] - reserved */
252 };
253
254 static const char *const m_urb_interleave[2] = { "", "interleaved" };
255
256 static const char *const m_rt_opcode[] = {
257 [0] = "SIMD16",
258 [1] = "RepData",
259 [2] = "DualLow",
260 [3] = "DualHigh",
261 [4] = "SIMD8",
262 [5] = "ImageWrite",
263 [6] = "Reserved",
264 [7] = "RepData(7)",
265 };
266
267 static int column;
268
269 static int
270 string(FILE *file, const char *string)
271 {
272 fputs(string, file);
273 column += strlen(string);
274 return 0;
275 }
276
277 static int
278 format(FILE *f, const char *format, ...)
279 {
280 char buf[1024];
281 va_list args;
282 va_start(args, format);
283
284 vsnprintf(buf, sizeof(buf) - 1, format, args);
285 va_end(args);
286 string(f, buf);
287 return 0;
288 }
289
290 static int
291 newline(FILE *f)
292 {
293 putc('\n', f);
294 column = 0;
295 return 0;
296 }
297
298 static int
299 pad(FILE *f, int c)
300 {
301 do
302 string(f, " ");
303 while (column < c);
304 return 0;
305 }
306
307 static int
308 control(FILE *file, const char *name, const char *const ctrl[],
309 unsigned id, int *space)
310 {
311 if (!ctrl[id]) {
312 fprintf(file, "*** invalid %s value %d ", name, id);
313 return 1;
314 }
315 if (ctrl[id][0]) {
316 if (space && *space)
317 string(file, " ");
318 string(file, ctrl[id]);
319 if (space)
320 *space = 1;
321 }
322 return 0;
323 }
324
325 static int
326 print_opcode(FILE *file, int id)
327 {
328 if (!m_opcode[id].name) {
329 format(file, "*** invalid opcode value %d ", id);
330 return 1;
331 }
332 string(file, m_opcode[id].name);
333 return 0;
334 }
335
336 static int
337 reg(FILE *file, unsigned reg_file, unsigned _reg_nr)
338 {
339 int err = 0;
340
341 if (reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
342 switch (_reg_nr & 0xf0) {
343 case BRW_ARF_NULL:
344 string(file, "null");
345 return -1;
346 case BRW_ARF_ADDRESS:
347 format(file, "a%d", _reg_nr & 0x0f);
348 break;
349 case BRW_ARF_ACCUMULATOR:
350 format(file, "acc%d", _reg_nr & 0x0f);
351 break;
352 case BRW_ARF_FLAG:
353 format(file, "f%d", _reg_nr & 0x0f);
354 break;
355 case BRW_ARF_MASK:
356 format(file, "mask%d", _reg_nr & 0x0f);
357 break;
358 case BRW_ARF_MASK_STACK:
359 format(file, "msd%d", _reg_nr & 0x0f);
360 break;
361 case BRW_ARF_STATE:
362 format(file, "sr%d", _reg_nr & 0x0f);
363 break;
364 case BRW_ARF_CONTROL:
365 format(file, "cr%d", _reg_nr & 0x0f);
366 break;
367 case BRW_ARF_NOTIFICATION_COUNT:
368 format(file, "n%d", _reg_nr & 0x0f);
369 break;
370 case BRW_ARF_IP:
371 string(file, "ip");
372 return -1;
373 break;
374 default:
375 format(file, "ARF%d", _reg_nr);
376 break;
377 }
378 } else {
379 err |= control(file, "src reg file", m_reg_file, reg_file, NULL);
380 format(file, "%d", _reg_nr);
381 }
382 return err;
383 }
384
385 static int
386 dest(FILE *file, struct gen8_instruction *inst)
387 {
388 int err = 0;
389
390 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
391 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
392 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
393 if (err == -1)
394 return 0;
395 if (gen8_dst_da1_subreg_nr(inst))
396 format(file, ".%d", gen8_dst_da1_subreg_nr(inst) /
397 reg_type_size[gen8_dst_reg_type(inst)]);
398 string(file, "<");
399 err |= control(file, "horiz stride", m_horiz_stride, gen8_dst_da1_hstride(inst), NULL);
400 string(file, ">");
401 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
402 } else {
403 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
404 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
405 if (err == -1)
406 return 0;
407 if (gen8_dst_da16_subreg_nr(inst))
408 format(file, ".%d", gen8_dst_da16_subreg_nr(inst) /
409 reg_type_size[gen8_dst_reg_type(inst)]);
410 string(file, "<1>");
411 err |= control(file, "writemask", m_writemask, gen8_da16_writemask(inst), NULL);
412 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
413 }
414
415 return 0;
416 }
417
418 static int
419 dest_3src(FILE *file, struct gen8_instruction *inst)
420 {
421 int err = 0;
422
423 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_dst_3src_reg_nr(inst));
424 if (err == -1)
425 return 0;
426 if (gen8_dst_3src_subreg_nr(inst))
427 format(file, ".%d", gen8_dst_3src_subreg_nr(inst));
428 string(file, "<1>");
429 err |= control(file, "writemask", m_writemask, gen8_dst_3src_writemask(inst),
430 NULL);
431 err |= control(file, "dest reg encoding", m_three_source_reg_encoding,
432 gen8_dst_3src_type(inst), NULL);
433
434 return 0;
435 }
436
437 static int
438 src_align1_region(FILE *file, unsigned vert_stride, unsigned _width,
439 unsigned horiz_stride)
440 {
441 int err = 0;
442 string(file, "<");
443 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
444 string(file, ",");
445 err |= control(file, "width", width, _width, NULL);
446 string(file, ",");
447 err |= control(file, "horiz_stride", m_horiz_stride, horiz_stride, NULL);
448 string(file, ">");
449 return err;
450 }
451
452 static int
453 src_swizzle(FILE *file, unsigned x, unsigned y, unsigned z, unsigned w)
454 {
455 int err = 0;
456
457 /* Three kinds of swizzle display:
458 * - identity - nothing printed
459 * - 1->all - print the single channel
460 * - 1->1 - print the mapping
461 */
462 if (x == BRW_CHANNEL_X &&
463 y == BRW_CHANNEL_Y &&
464 z == BRW_CHANNEL_Z &&
465 w == BRW_CHANNEL_W) {
466 ; /* Print nothing */
467 } else if (x == y && x == z && x == w) {
468 string(file, ".");
469 err |= control(file, "channel select", m_chan_sel, x, NULL);
470 } else {
471 string(file, ".");
472 err |= control(file, "channel select", m_chan_sel, x, NULL);
473 err |= control(file, "channel select", m_chan_sel, y, NULL);
474 err |= control(file, "channel select", m_chan_sel, z, NULL);
475 err |= control(file, "channel select", m_chan_sel, w, NULL);
476 }
477 return err;
478 }
479
480 static int
481 src_da1(FILE *file, unsigned type, unsigned reg_file,
482 unsigned vert_stride, unsigned _width, unsigned horiz_stride,
483 unsigned reg_num, unsigned sub_reg_num, unsigned _abs, unsigned negate)
484 {
485 int err = 0;
486 err |= control(file, "negate", m_negate, negate, NULL);
487 err |= control(file, "abs", m_abs, _abs, NULL);
488
489 err |= reg(file, reg_file, reg_num);
490 if (err == -1)
491 return 0;
492 if (sub_reg_num)
493 format(file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
494 src_align1_region(file, vert_stride, _width, horiz_stride);
495 err |= control(file, "src reg encoding", m_reg_encoding, type, NULL);
496 return err;
497 }
498
499 static int
500 src_da16(FILE *file,
501 unsigned _reg_type,
502 unsigned reg_file,
503 unsigned vert_stride,
504 unsigned _reg_nr,
505 unsigned _subreg_nr,
506 unsigned _abs,
507 unsigned negate,
508 unsigned swz_x,
509 unsigned swz_y,
510 unsigned swz_z,
511 unsigned swz_w)
512 {
513 int err = 0;
514 err |= control(file, "negate", m_negate, negate, NULL);
515 err |= control(file, "abs", m_abs, _abs, NULL);
516
517 err |= reg(file, reg_file, _reg_nr);
518 if (err == -1)
519 return 0;
520 if (_subreg_nr)
521 /* bit4 for subreg number byte addressing. Make this same meaning as
522 * in da1 case, so output looks consistent.
523 */
524 format(file, ".%d", 16 / reg_type_size[_reg_type]);
525 string(file, "<");
526 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
527 string(file, ",4,1>");
528 /*
529 * Three kinds of swizzle display:
530 * identity - nothing printed
531 * 1->all - print the single channel
532 * 1->1 - print the mapping
533 */
534 if (swz_x == BRW_CHANNEL_X &&
535 swz_y == BRW_CHANNEL_Y &&
536 swz_z == BRW_CHANNEL_Z &&
537 swz_w == BRW_CHANNEL_W) {
538 ; /* Print nothing */
539 } else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) {
540 string(file, ".");
541 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
542 } else {
543 string(file, ".");
544 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
545 err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
546 err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
547 err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
548 }
549 err |= control(file, "src da16 reg type", m_reg_encoding, _reg_type, NULL);
550 return err;
551 }
552
553 static int
554 src0_3src(FILE *file, struct gen8_instruction *inst)
555 {
556 int err = 0;
557 unsigned swiz = gen8_src0_3src_swizzle(inst);
558 unsigned swz_x = (swiz >> 0) & 0x3;
559 unsigned swz_y = (swiz >> 2) & 0x3;
560 unsigned swz_z = (swiz >> 4) & 0x3;
561 unsigned swz_w = (swiz >> 6) & 0x3;
562
563 err |= control(file, "negate", m_negate, gen8_src0_3src_negate(inst), NULL);
564 err |= control(file, "abs", m_abs, gen8_src0_3src_abs(inst), NULL);
565
566 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src0_3src_reg_nr(inst));
567 if (err == -1)
568 return 0;
569 if (gen8_src0_3src_subreg_nr(inst))
570 format(file, ".%d", gen8_src0_3src_subreg_nr(inst));
571 string(file, "<4,1,1>");
572 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
573 gen8_src_3src_type(inst), NULL);
574 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
575 return err;
576 }
577
578 static int
579 src1_3src(FILE *file, struct gen8_instruction *inst)
580 {
581 int err = 0;
582 unsigned swiz = gen8_src1_3src_swizzle(inst);
583 unsigned swz_x = (swiz >> 0) & 0x3;
584 unsigned swz_y = (swiz >> 2) & 0x3;
585 unsigned swz_z = (swiz >> 4) & 0x3;
586 unsigned swz_w = (swiz >> 6) & 0x3;
587 unsigned src1_subreg_nr = gen8_src1_3src_subreg_nr(inst);
588
589 err |= control(file, "negate", m_negate, gen8_src1_3src_negate(inst), NULL);
590 err |= control(file, "abs", m_abs, gen8_src1_3src_abs(inst), NULL);
591
592 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src1_3src_reg_nr(inst));
593 if (err == -1)
594 return 0;
595 if (src1_subreg_nr)
596 format(file, ".%d", src1_subreg_nr);
597 string(file, "<4,1,1>");
598 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
599 gen8_src_3src_type(inst), NULL);
600 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
601 return err;
602 }
603
604 static int
605 src2_3src(FILE *file, struct gen8_instruction *inst)
606 {
607 int err = 0;
608 unsigned swiz = gen8_src2_3src_swizzle(inst);
609 unsigned swz_x = (swiz >> 0) & 0x3;
610 unsigned swz_y = (swiz >> 2) & 0x3;
611 unsigned swz_z = (swiz >> 4) & 0x3;
612 unsigned swz_w = (swiz >> 6) & 0x3;
613
614 err |= control(file, "negate", m_negate, gen8_src2_3src_negate(inst), NULL);
615 err |= control(file, "abs", m_abs, gen8_src2_3src_abs(inst), NULL);
616
617 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src2_3src_reg_nr(inst));
618 if (err == -1)
619 return 0;
620 if (gen8_src2_3src_subreg_nr(inst))
621 format(file, ".%d", gen8_src2_3src_subreg_nr(inst));
622 string(file, "<4,1,1>");
623 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
624 gen8_src_3src_type(inst), NULL);
625 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
626 return err;
627 }
628
629 static int
630 imm(FILE *file, unsigned type, struct gen8_instruction *inst)
631 {
632 switch (type) {
633 case BRW_HW_REG_TYPE_UD:
634 format(file, "0x%08xUD", gen8_src1_imm_ud(inst));
635 break;
636 case BRW_HW_REG_TYPE_D:
637 format(file, "%dD", gen8_src1_imm_d(inst));
638 break;
639 case BRW_HW_REG_TYPE_UW:
640 format(file, "0x%04xUW", (uint16_t) gen8_src1_imm_ud(inst));
641 break;
642 case BRW_HW_REG_TYPE_W:
643 format(file, "%dW", (int16_t) gen8_src1_imm_d(inst));
644 break;
645 case BRW_HW_REG_IMM_TYPE_UV:
646 format(file, "0x%08xUV", gen8_src1_imm_ud(inst));
647 break;
648 case BRW_HW_REG_IMM_TYPE_VF:
649 format(file, "Vector Float");
650 break;
651 case BRW_HW_REG_IMM_TYPE_V:
652 format(file, "0x%08xV", gen8_src1_imm_ud(inst));
653 break;
654 case BRW_HW_REG_TYPE_F:
655 format(file, "%-gF", gen8_src1_imm_f(inst));
656 break;
657 case GEN8_HW_REG_IMM_TYPE_DF:
658 case GEN8_HW_REG_IMM_TYPE_HF:
659 assert(!"Not implemented yet");
660 break;
661 }
662 return 0;
663 }
664
665 static int
666 src0(FILE *file, struct gen8_instruction *inst)
667 {
668 if (gen8_src0_reg_file(inst) == BRW_IMMEDIATE_VALUE)
669 return imm(file, gen8_src0_reg_type(inst), inst);
670
671 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
672 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
673 return src_da1(file,
674 gen8_src0_reg_type(inst),
675 gen8_src0_reg_file(inst),
676 gen8_src0_vert_stride(inst),
677 gen8_src0_da1_width(inst),
678 gen8_src0_da1_hstride(inst),
679 gen8_src0_da_reg_nr(inst),
680 gen8_src0_da1_subreg_nr(inst),
681 gen8_src0_abs(inst),
682 gen8_src0_negate(inst));
683 } else {
684 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
685 return src_da16(file,
686 gen8_src0_reg_type(inst),
687 gen8_src0_reg_file(inst),
688 gen8_src0_vert_stride(inst),
689 gen8_src0_da_reg_nr(inst),
690 gen8_src0_da16_subreg_nr(inst),
691 gen8_src0_abs(inst),
692 gen8_src0_negate(inst),
693 gen8_src0_da16_swiz_x(inst),
694 gen8_src0_da16_swiz_y(inst),
695 gen8_src0_da16_swiz_z(inst),
696 gen8_src0_da16_swiz_w(inst));
697 }
698 }
699
700 static int
701 src1(FILE *file, struct gen8_instruction *inst)
702 {
703 if (gen8_src1_reg_file(inst) == BRW_IMMEDIATE_VALUE)
704 return imm(file, gen8_src1_reg_type(inst), inst);
705
706 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
707 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
708 return src_da1(file,
709 gen8_src1_reg_type(inst),
710 gen8_src1_reg_file(inst),
711 gen8_src1_vert_stride(inst),
712 gen8_src1_da1_width(inst),
713 gen8_src1_da1_hstride(inst),
714 gen8_src1_da_reg_nr(inst),
715 gen8_src1_da1_subreg_nr(inst),
716 gen8_src1_abs(inst),
717 gen8_src1_negate(inst));
718 } else {
719 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
720 return src_da16(file,
721 gen8_src1_reg_type(inst),
722 gen8_src1_reg_file(inst),
723 gen8_src1_vert_stride(inst),
724 gen8_src1_da_reg_nr(inst),
725 gen8_src1_da16_subreg_nr(inst),
726 gen8_src1_abs(inst),
727 gen8_src1_negate(inst),
728 gen8_src1_da16_swiz_x(inst),
729 gen8_src1_da16_swiz_y(inst),
730 gen8_src1_da16_swiz_z(inst),
731 gen8_src1_da16_swiz_w(inst));
732 }
733 }
734
735 static int esize[6] = { 1, 2, 4, 8, 16, 32 };
736
737 static int
738 qtr_ctrl(FILE *file, struct gen8_instruction *inst)
739 {
740 int qtr_ctl = gen8_qtr_control(inst);
741 int exec_size = esize[gen8_exec_size(inst)];
742
743 if (exec_size == 8) {
744 switch (qtr_ctl) {
745 case 0:
746 string(file, " 1Q");
747 break;
748 case 1:
749 string(file, " 2Q");
750 break;
751 case 2:
752 string(file, " 3Q");
753 break;
754 case 3:
755 string(file, " 4Q");
756 break;
757 }
758 } else if (exec_size == 16) {
759 if (qtr_ctl < 2)
760 string(file, " 1H");
761 else
762 string(file, " 2H");
763 }
764 return 0;
765 }
766
767 int
768 gen8_disassemble(FILE *file, struct gen8_instruction *inst, int gen)
769 {
770 int err = 0;
771 int space = 0;
772
773 const int opcode = gen8_opcode(inst);
774
775 if (gen8_pred_control(inst)) {
776 string(file, "(");
777 err |= control(file, "predicate inverse", m_pred_inv, gen8_pred_inv(inst), NULL);
778 format(file, "f%d", gen8_flag_reg_nr(inst));
779 if (gen8_flag_subreg_nr(inst))
780 format(file, ".%d", gen8_flag_subreg_nr(inst));
781 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
782 err |= control(file, "predicate control align1", m_pred_ctrl_align1,
783 gen8_pred_control(inst), NULL);
784 } else {
785 err |= control(file, "predicate control align16", m_pred_ctrl_align16,
786 gen8_pred_control(inst), NULL);
787 }
788 string(file, ") ");
789 }
790
791 err |= print_opcode(file, opcode);
792 err |= control(file, "saturate", m_saturate, gen8_saturate(inst), NULL);
793 err |= control(file, "debug control", m_debug_ctrl, gen8_debug_control(inst), NULL);
794
795 if (opcode == BRW_OPCODE_MATH) {
796 string(file, " ");
797 err |= control(file, "function", m_math_function, gen8_math_function(inst),
798 NULL);
799 } else if (opcode != BRW_OPCODE_SEND && opcode != BRW_OPCODE_SENDC) {
800 err |= control(file, "conditional modifier", m_conditional_modifier,
801 gen8_cond_modifier(inst), NULL);
802
803 /* If we're using the conditional modifier, print the flag reg used. */
804 if (gen8_cond_modifier(inst) && opcode != BRW_OPCODE_SEL) {
805 format(file, ".f%d", gen8_flag_reg_nr(inst));
806 if (gen8_flag_subreg_nr(inst))
807 format(file, ".%d", gen8_flag_subreg_nr(inst));
808 }
809 }
810
811 if (opcode != BRW_OPCODE_NOP) {
812 string(file, "(");
813 err |= control(file, "execution size", m_exec_size, gen8_exec_size(inst), NULL);
814 string(file, ")");
815 }
816
817 if (m_opcode[opcode].nsrc == 3) {
818 pad(file, 16);
819 err |= dest_3src(file, inst);
820
821 pad(file, 32);
822 err |= src0_3src(file, inst);
823
824 pad(file, 48);
825 err |= src1_3src(file, inst);
826
827 pad(file, 64);
828 err |= src2_3src(file, inst);
829 } else {
830 if (m_opcode[opcode].ndst > 0) {
831 pad(file, 16);
832 err |= dest(file, inst);
833 } else if (opcode == BRW_OPCODE_ENDIF) {
834 format(file, " %d", gen8_jip(inst));
835 } else if (opcode == BRW_OPCODE_IF ||
836 opcode == BRW_OPCODE_ELSE ||
837 opcode == BRW_OPCODE_WHILE ||
838 opcode == BRW_OPCODE_BREAK ||
839 opcode == BRW_OPCODE_CONTINUE ||
840 opcode == BRW_OPCODE_HALT) {
841 format(file, " %d %d", gen8_jip(inst), gen8_uip(inst));
842 }
843
844 if (m_opcode[opcode].nsrc > 0) {
845 pad(file, 32);
846 err |= src0(file, inst);
847 }
848 if (m_opcode[opcode].nsrc > 1) {
849 pad(file, 48);
850 err |= src1(file, inst);
851 }
852 }
853
854 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC) {
855 const int sfid = gen8_sfid(inst);
856
857 newline(file);
858 pad(file, 16);
859 space = 0;
860
861 err |= control(file, "SFID", m_sfid, sfid, &space);
862
863 switch (sfid) {
864 case BRW_SFID_SAMPLER:
865 format(file, " (%d, %d, %d, %d)",
866 gen8_binding_table_index(inst),
867 gen8_sampler(inst),
868 gen8_sampler_msg_type(inst),
869 gen8_sampler_simd_mode(inst));
870 break;
871
872 case BRW_SFID_URB:
873 space = 1;
874 err |= control(file, "urb opcode", m_urb_opcode,
875 gen8_urb_opcode(inst), &space);
876 err |= control(file, "urb interleave", m_urb_interleave,
877 gen8_urb_interleave(inst), &space);
878 format(file, " %d %d",
879 gen8_urb_global_offset(inst), gen8_urb_per_slot_offset(inst));
880 break;
881
882 case GEN6_SFID_DATAPORT_RENDER_CACHE: {
883 err |= control(file, "rt message", m_rt_opcode,
884 gen8_rt_message_type(inst), &space);
885 format(file, " %s%sSurface = %d",
886 gen8_rt_slot_group(inst) ? "Hi " : "",
887 gen8_rt_last(inst) ? "LastRT " : "",
888 gen8_binding_table_index(inst));
889 break;
890 }
891
892 case GEN6_SFID_DATAPORT_SAMPLER_CACHE:
893 case GEN6_SFID_DATAPORT_CONSTANT_CACHE:
894 case GEN7_SFID_DATAPORT_DATA_CACHE:
895 format(file, " (%d, 0x%x)",
896 gen8_binding_table_index(inst),
897 gen8_function_control(inst));
898 break;
899
900 default:
901 format(file, "unsupported shared function ID (%d)", sfid);
902 break;
903 }
904 if (space)
905 string(file, " ");
906 format(file, "mlen %d", gen8_mlen(inst));
907 format(file, " rlen %d", gen8_rlen(inst));
908 }
909 pad(file, 64);
910 if (opcode != BRW_OPCODE_NOP) {
911 string(file, "{");
912 space = 1;
913 err |= control(file, "access mode", m_access_mode, gen8_access_mode(inst), &space);
914 err |= control(file, "mask control", m_maskctrl, gen8_mask_control(inst), &space);
915 err |= control(file, "DDClr", m_dep_clear, gen8_no_dd_clear(inst), &space);
916 err |= control(file, "DDChk", m_dep_check, gen8_no_dd_check(inst), &space);
917
918 err |= qtr_ctrl(file, inst);
919
920 err |= control(file, "thread control", m_thread_ctrl, gen8_thread_control(inst), &space);
921 err |= control(file, "acc write control", m_accwr, gen8_acc_wr_control(inst), &space);
922 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC)
923 err |= control(file, "end of thread", m_eot, gen8_eot(inst), &space);
924 if (space)
925 string(file, " ");
926 string(file, "}");
927 }
928 string(file, ";");
929 newline(file);
930 return err;
931 }