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